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