1 /*
2  * Crypto wrapper for internal crypto implementation
3  * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "common.h"
12 #include "crypto.h"
13 #include "sha256_i.h"
14 #include "sha1_i.h"
15 #include "md5_i.h"
16 
17 struct crypto_hash {
18 	enum crypto_hash_alg alg;
19 	union {
20 		struct MD5Context md5;
21 		struct SHA1Context sha1;
22 #ifdef CONFIG_SHA256
23 		struct sha256_state sha256;
24 #endif /* CONFIG_SHA256 */
25 	} u;
26 	u8 key[64];
27 	size_t key_len;
28 };
29 
30 
31 struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
32 				      size_t key_len)
33 {
34 	struct crypto_hash *ctx;
35 	u8 k_pad[64];
36 	u8 tk[32];
37 	size_t i;
38 
39 	ctx = os_zalloc(sizeof(*ctx));
40 	if (ctx == NULL)
41 		return NULL;
42 
43 	ctx->alg = alg;
44 
45 	switch (alg) {
46 	case CRYPTO_HASH_ALG_MD5:
47 		MD5Init(&ctx->u.md5);
48 		break;
49 	case CRYPTO_HASH_ALG_SHA1:
50 		SHA1Init(&ctx->u.sha1);
51 		break;
52 #ifdef CONFIG_SHA256
53 	case CRYPTO_HASH_ALG_SHA256:
54 		sha256_init(&ctx->u.sha256);
55 		break;
56 #endif /* CONFIG_SHA256 */
57 	case CRYPTO_HASH_ALG_HMAC_MD5:
58 		if (key_len > sizeof(k_pad)) {
59 			MD5Init(&ctx->u.md5);
60 			MD5Update(&ctx->u.md5, key, key_len);
61 			MD5Final(tk, &ctx->u.md5);
62 			key = tk;
63 			key_len = 16;
64 		}
65 		os_memcpy(ctx->key, key, key_len);
66 		ctx->key_len = key_len;
67 
68 		os_memcpy(k_pad, key, key_len);
69 		if (key_len < sizeof(k_pad))
70 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
71 		for (i = 0; i < sizeof(k_pad); i++)
72 			k_pad[i] ^= 0x36;
73 		MD5Init(&ctx->u.md5);
74 		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
75 		break;
76 	case CRYPTO_HASH_ALG_HMAC_SHA1:
77 		if (key_len > sizeof(k_pad)) {
78 			SHA1Init(&ctx->u.sha1);
79 			SHA1Update(&ctx->u.sha1, key, key_len);
80 			SHA1Final(tk, &ctx->u.sha1);
81 			key = tk;
82 			key_len = 20;
83 		}
84 		os_memcpy(ctx->key, key, key_len);
85 		ctx->key_len = key_len;
86 
87 		os_memcpy(k_pad, key, key_len);
88 		if (key_len < sizeof(k_pad))
89 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
90 		for (i = 0; i < sizeof(k_pad); i++)
91 			k_pad[i] ^= 0x36;
92 		SHA1Init(&ctx->u.sha1);
93 		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
94 		break;
95 #ifdef CONFIG_SHA256
96 	case CRYPTO_HASH_ALG_HMAC_SHA256:
97 		if (key_len > sizeof(k_pad)) {
98 			sha256_init(&ctx->u.sha256);
99 			sha256_process(&ctx->u.sha256, key, key_len);
100 			sha256_done(&ctx->u.sha256, tk);
101 			key = tk;
102 			key_len = 32;
103 		}
104 		os_memcpy(ctx->key, key, key_len);
105 		ctx->key_len = key_len;
106 
107 		os_memcpy(k_pad, key, key_len);
108 		if (key_len < sizeof(k_pad))
109 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
110 		for (i = 0; i < sizeof(k_pad); i++)
111 			k_pad[i] ^= 0x36;
112 		sha256_init(&ctx->u.sha256);
113 		sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
114 		break;
115 #endif /* CONFIG_SHA256 */
116 	default:
117 		os_free(ctx);
118 		return NULL;
119 	}
120 
121 	return ctx;
122 }
123 
124 
125 void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
126 {
127 	if (ctx == NULL)
128 		return;
129 
130 	switch (ctx->alg) {
131 	case CRYPTO_HASH_ALG_MD5:
132 	case CRYPTO_HASH_ALG_HMAC_MD5:
133 		MD5Update(&ctx->u.md5, data, len);
134 		break;
135 	case CRYPTO_HASH_ALG_SHA1:
136 	case CRYPTO_HASH_ALG_HMAC_SHA1:
137 		SHA1Update(&ctx->u.sha1, data, len);
138 		break;
139 #ifdef CONFIG_SHA256
140 	case CRYPTO_HASH_ALG_SHA256:
141 	case CRYPTO_HASH_ALG_HMAC_SHA256:
142 		sha256_process(&ctx->u.sha256, data, len);
143 		break;
144 #endif /* CONFIG_SHA256 */
145 	default:
146 		break;
147 	}
148 }
149 
150 
151 int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
152 {
153 	u8 k_pad[64];
154 	size_t i;
155 
156 	if (ctx == NULL)
157 		return -2;
158 
159 	if (mac == NULL || len == NULL) {
160 		os_free(ctx);
161 		return 0;
162 	}
163 
164 	switch (ctx->alg) {
165 	case CRYPTO_HASH_ALG_MD5:
166 		if (*len < 16) {
167 			*len = 16;
168 			os_free(ctx);
169 			return -1;
170 		}
171 		*len = 16;
172 		MD5Final(mac, &ctx->u.md5);
173 		break;
174 	case CRYPTO_HASH_ALG_SHA1:
175 		if (*len < 20) {
176 			*len = 20;
177 			os_free(ctx);
178 			return -1;
179 		}
180 		*len = 20;
181 		SHA1Final(mac, &ctx->u.sha1);
182 		break;
183 #ifdef CONFIG_SHA256
184 	case CRYPTO_HASH_ALG_SHA256:
185 		if (*len < 32) {
186 			*len = 32;
187 			os_free(ctx);
188 			return -1;
189 		}
190 		*len = 32;
191 		sha256_done(&ctx->u.sha256, mac);
192 		break;
193 #endif /* CONFIG_SHA256 */
194 	case CRYPTO_HASH_ALG_HMAC_MD5:
195 		if (*len < 16) {
196 			*len = 16;
197 			os_free(ctx);
198 			return -1;
199 		}
200 		*len = 16;
201 
202 		MD5Final(mac, &ctx->u.md5);
203 
204 		os_memcpy(k_pad, ctx->key, ctx->key_len);
205 		os_memset(k_pad + ctx->key_len, 0,
206 			  sizeof(k_pad) - ctx->key_len);
207 		for (i = 0; i < sizeof(k_pad); i++)
208 			k_pad[i] ^= 0x5c;
209 		MD5Init(&ctx->u.md5);
210 		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
211 		MD5Update(&ctx->u.md5, mac, 16);
212 		MD5Final(mac, &ctx->u.md5);
213 		break;
214 	case CRYPTO_HASH_ALG_HMAC_SHA1:
215 		if (*len < 20) {
216 			*len = 20;
217 			os_free(ctx);
218 			return -1;
219 		}
220 		*len = 20;
221 
222 		SHA1Final(mac, &ctx->u.sha1);
223 
224 		os_memcpy(k_pad, ctx->key, ctx->key_len);
225 		os_memset(k_pad + ctx->key_len, 0,
226 			  sizeof(k_pad) - ctx->key_len);
227 		for (i = 0; i < sizeof(k_pad); i++)
228 			k_pad[i] ^= 0x5c;
229 		SHA1Init(&ctx->u.sha1);
230 		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
231 		SHA1Update(&ctx->u.sha1, mac, 20);
232 		SHA1Final(mac, &ctx->u.sha1);
233 		break;
234 #ifdef CONFIG_SHA256
235 	case CRYPTO_HASH_ALG_HMAC_SHA256:
236 		if (*len < 32) {
237 			*len = 32;
238 			os_free(ctx);
239 			return -1;
240 		}
241 		*len = 32;
242 
243 		sha256_done(&ctx->u.sha256, mac);
244 
245 		os_memcpy(k_pad, ctx->key, ctx->key_len);
246 		os_memset(k_pad + ctx->key_len, 0,
247 			  sizeof(k_pad) - ctx->key_len);
248 		for (i = 0; i < sizeof(k_pad); i++)
249 			k_pad[i] ^= 0x5c;
250 		sha256_init(&ctx->u.sha256);
251 		sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
252 		sha256_process(&ctx->u.sha256, mac, 32);
253 		sha256_done(&ctx->u.sha256, mac);
254 		break;
255 #endif /* CONFIG_SHA256 */
256 	default:
257 		os_free(ctx);
258 		return -1;
259 	}
260 
261 	os_free(ctx);
262 
263 	return 0;
264 }
265 
266 
267 int crypto_global_init(void)
268 {
269 	return 0;
270 }
271 
272 
273 void crypto_global_deinit(void)
274 {
275 }
276