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 #ifdef CONFIG_INTERNAL_SHA384
26 		struct sha384_state sha384;
27 #endif /* CONFIG_INTERNAL_SHA384 */
28 #ifdef CONFIG_INTERNAL_SHA512
29 		struct sha512_state sha512;
30 #endif /* CONFIG_INTERNAL_SHA512 */
31 	} u;
32 	u8 key[64];
33 	size_t key_len;
34 };
35 
36 
crypto_hash_init(enum crypto_hash_alg alg,const u8 * key,size_t key_len)37 struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
38 				      size_t key_len)
39 {
40 	struct crypto_hash *ctx;
41 	u8 k_pad[64];
42 	u8 tk[32];
43 	size_t i;
44 
45 	ctx = os_zalloc(sizeof(*ctx));
46 	if (ctx == NULL)
47 		return NULL;
48 
49 	ctx->alg = alg;
50 
51 	switch (alg) {
52 	case CRYPTO_HASH_ALG_MD5:
53 		MD5Init(&ctx->u.md5);
54 		break;
55 	case CRYPTO_HASH_ALG_SHA1:
56 		SHA1Init(&ctx->u.sha1);
57 		break;
58 #ifdef CONFIG_SHA256
59 	case CRYPTO_HASH_ALG_SHA256:
60 		sha256_init(&ctx->u.sha256);
61 		break;
62 #endif /* CONFIG_SHA256 */
63 #ifdef CONFIG_INTERNAL_SHA384
64 	case CRYPTO_HASH_ALG_SHA384:
65 		sha384_init(&ctx->u.sha384);
66 		break;
67 #endif /* CONFIG_INTERNAL_SHA384 */
68 #ifdef CONFIG_INTERNAL_SHA512
69 	case CRYPTO_HASH_ALG_SHA512:
70 		sha512_init(&ctx->u.sha512);
71 		break;
72 #endif /* CONFIG_INTERNAL_SHA512 */
73 	case CRYPTO_HASH_ALG_HMAC_MD5:
74 		if (key_len > sizeof(k_pad)) {
75 			MD5Init(&ctx->u.md5);
76 			MD5Update(&ctx->u.md5, key, key_len);
77 			MD5Final(tk, &ctx->u.md5);
78 			key = tk;
79 			key_len = 16;
80 		}
81 		os_memcpy(ctx->key, key, key_len);
82 		ctx->key_len = key_len;
83 
84 		os_memcpy(k_pad, key, key_len);
85 		if (key_len < sizeof(k_pad))
86 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
87 		for (i = 0; i < sizeof(k_pad); i++)
88 			k_pad[i] ^= 0x36;
89 		MD5Init(&ctx->u.md5);
90 		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
91 		break;
92 	case CRYPTO_HASH_ALG_HMAC_SHA1:
93 		if (key_len > sizeof(k_pad)) {
94 			SHA1Init(&ctx->u.sha1);
95 			SHA1Update(&ctx->u.sha1, key, key_len);
96 			SHA1Final(tk, &ctx->u.sha1);
97 			key = tk;
98 			key_len = 20;
99 		}
100 		os_memcpy(ctx->key, key, key_len);
101 		ctx->key_len = key_len;
102 
103 		os_memcpy(k_pad, key, key_len);
104 		if (key_len < sizeof(k_pad))
105 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
106 		for (i = 0; i < sizeof(k_pad); i++)
107 			k_pad[i] ^= 0x36;
108 		SHA1Init(&ctx->u.sha1);
109 		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
110 		break;
111 #ifdef CONFIG_SHA256
112 	case CRYPTO_HASH_ALG_HMAC_SHA256:
113 		if (key_len > sizeof(k_pad)) {
114 			sha256_init(&ctx->u.sha256);
115 			sha256_process(&ctx->u.sha256, key, key_len);
116 			sha256_done(&ctx->u.sha256, tk);
117 			key = tk;
118 			key_len = 32;
119 		}
120 		os_memcpy(ctx->key, key, key_len);
121 		ctx->key_len = key_len;
122 
123 		os_memcpy(k_pad, key, key_len);
124 		if (key_len < sizeof(k_pad))
125 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
126 		for (i = 0; i < sizeof(k_pad); i++)
127 			k_pad[i] ^= 0x36;
128 		sha256_init(&ctx->u.sha256);
129 		sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
130 		break;
131 #endif /* CONFIG_SHA256 */
132 	default:
133 		os_free(ctx);
134 		return NULL;
135 	}
136 
137 	return ctx;
138 }
139 
140 
crypto_hash_update(struct crypto_hash * ctx,const u8 * data,size_t len)141 void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
142 {
143 	if (ctx == NULL)
144 		return;
145 
146 	switch (ctx->alg) {
147 	case CRYPTO_HASH_ALG_MD5:
148 	case CRYPTO_HASH_ALG_HMAC_MD5:
149 		MD5Update(&ctx->u.md5, data, len);
150 		break;
151 	case CRYPTO_HASH_ALG_SHA1:
152 	case CRYPTO_HASH_ALG_HMAC_SHA1:
153 		SHA1Update(&ctx->u.sha1, data, len);
154 		break;
155 #ifdef CONFIG_SHA256
156 	case CRYPTO_HASH_ALG_SHA256:
157 	case CRYPTO_HASH_ALG_HMAC_SHA256:
158 		sha256_process(&ctx->u.sha256, data, len);
159 		break;
160 #endif /* CONFIG_SHA256 */
161 #ifdef CONFIG_INTERNAL_SHA384
162 	case CRYPTO_HASH_ALG_SHA384:
163 		sha384_process(&ctx->u.sha384, data, len);
164 		break;
165 #endif /* CONFIG_INTERNAL_SHA384 */
166 #ifdef CONFIG_INTERNAL_SHA512
167 	case CRYPTO_HASH_ALG_SHA512:
168 		sha512_process(&ctx->u.sha512, data, len);
169 		break;
170 #endif /* CONFIG_INTERNAL_SHA512 */
171 	default:
172 		break;
173 	}
174 }
175 
176 
crypto_hash_finish(struct crypto_hash * ctx,u8 * mac,size_t * len)177 int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
178 {
179 	u8 k_pad[64];
180 	size_t i;
181 
182 	if (ctx == NULL)
183 		return -2;
184 
185 	if (mac == NULL || len == NULL) {
186 		os_free(ctx);
187 		return 0;
188 	}
189 
190 	switch (ctx->alg) {
191 	case CRYPTO_HASH_ALG_MD5:
192 		if (*len < 16) {
193 			*len = 16;
194 			os_free(ctx);
195 			return -1;
196 		}
197 		*len = 16;
198 		MD5Final(mac, &ctx->u.md5);
199 		break;
200 	case CRYPTO_HASH_ALG_SHA1:
201 		if (*len < 20) {
202 			*len = 20;
203 			os_free(ctx);
204 			return -1;
205 		}
206 		*len = 20;
207 		SHA1Final(mac, &ctx->u.sha1);
208 		break;
209 #ifdef CONFIG_SHA256
210 	case CRYPTO_HASH_ALG_SHA256:
211 		if (*len < 32) {
212 			*len = 32;
213 			os_free(ctx);
214 			return -1;
215 		}
216 		*len = 32;
217 		sha256_done(&ctx->u.sha256, mac);
218 		break;
219 #endif /* CONFIG_SHA256 */
220 #ifdef CONFIG_INTERNAL_SHA384
221 	case CRYPTO_HASH_ALG_SHA384:
222 		if (*len < 48) {
223 			*len = 48;
224 			os_free(ctx);
225 			return -1;
226 		}
227 		*len = 48;
228 		sha384_done(&ctx->u.sha384, mac);
229 		break;
230 #endif /* CONFIG_INTERNAL_SHA384 */
231 #ifdef CONFIG_INTERNAL_SHA512
232 	case CRYPTO_HASH_ALG_SHA512:
233 		if (*len < 64) {
234 			*len = 64;
235 			os_free(ctx);
236 			return -1;
237 		}
238 		*len = 64;
239 		sha512_done(&ctx->u.sha512, mac);
240 		break;
241 #endif /* CONFIG_INTERNAL_SHA512 */
242 	case CRYPTO_HASH_ALG_HMAC_MD5:
243 		if (*len < 16) {
244 			*len = 16;
245 			os_free(ctx);
246 			return -1;
247 		}
248 		*len = 16;
249 
250 		MD5Final(mac, &ctx->u.md5);
251 
252 		os_memcpy(k_pad, ctx->key, ctx->key_len);
253 		os_memset(k_pad + ctx->key_len, 0,
254 			  sizeof(k_pad) - ctx->key_len);
255 		for (i = 0; i < sizeof(k_pad); i++)
256 			k_pad[i] ^= 0x5c;
257 		MD5Init(&ctx->u.md5);
258 		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
259 		MD5Update(&ctx->u.md5, mac, 16);
260 		MD5Final(mac, &ctx->u.md5);
261 		break;
262 	case CRYPTO_HASH_ALG_HMAC_SHA1:
263 		if (*len < 20) {
264 			*len = 20;
265 			os_free(ctx);
266 			return -1;
267 		}
268 		*len = 20;
269 
270 		SHA1Final(mac, &ctx->u.sha1);
271 
272 		os_memcpy(k_pad, ctx->key, ctx->key_len);
273 		os_memset(k_pad + ctx->key_len, 0,
274 			  sizeof(k_pad) - ctx->key_len);
275 		for (i = 0; i < sizeof(k_pad); i++)
276 			k_pad[i] ^= 0x5c;
277 		SHA1Init(&ctx->u.sha1);
278 		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
279 		SHA1Update(&ctx->u.sha1, mac, 20);
280 		SHA1Final(mac, &ctx->u.sha1);
281 		break;
282 #ifdef CONFIG_SHA256
283 	case CRYPTO_HASH_ALG_HMAC_SHA256:
284 		if (*len < 32) {
285 			*len = 32;
286 			os_free(ctx);
287 			return -1;
288 		}
289 		*len = 32;
290 
291 		sha256_done(&ctx->u.sha256, mac);
292 
293 		os_memcpy(k_pad, ctx->key, ctx->key_len);
294 		os_memset(k_pad + ctx->key_len, 0,
295 			  sizeof(k_pad) - ctx->key_len);
296 		for (i = 0; i < sizeof(k_pad); i++)
297 			k_pad[i] ^= 0x5c;
298 		sha256_init(&ctx->u.sha256);
299 		sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
300 		sha256_process(&ctx->u.sha256, mac, 32);
301 		sha256_done(&ctx->u.sha256, mac);
302 		break;
303 #endif /* CONFIG_SHA256 */
304 	default:
305 		os_free(ctx);
306 		return -1;
307 	}
308 
309 	os_free(ctx);
310 
311 	if (TEST_FAIL())
312 		return -1;
313 
314 	return 0;
315 }
316 
317 
crypto_global_init(void)318 int crypto_global_init(void)
319 {
320 	return 0;
321 }
322 
323 
crypto_global_deinit(void)324 void crypto_global_deinit(void)
325 {
326 }
327