xref: /freebsd/contrib/wpa/src/crypto/crypto_internal.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
139beb93cSSam Leffler /*
2e28a4053SRui Paulo  * Crypto wrapper for internal crypto implementation
3f05cddf9SRui Paulo  * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
5f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
6f05cddf9SRui Paulo  * See README for more details.
739beb93cSSam Leffler  */
839beb93cSSam Leffler 
939beb93cSSam Leffler #include "includes.h"
1039beb93cSSam Leffler 
1139beb93cSSam Leffler #include "common.h"
1239beb93cSSam Leffler #include "crypto.h"
13f05cddf9SRui Paulo #include "sha256_i.h"
14780fb4a2SCy Schubert #include "sha384_i.h"
15780fb4a2SCy Schubert #include "sha512_i.h"
16e28a4053SRui Paulo #include "sha1_i.h"
17e28a4053SRui Paulo #include "md5_i.h"
1839beb93cSSam Leffler 
1939beb93cSSam Leffler struct crypto_hash {
2039beb93cSSam Leffler 	enum crypto_hash_alg alg;
2139beb93cSSam Leffler 	union {
2239beb93cSSam Leffler 		struct MD5Context md5;
2339beb93cSSam Leffler 		struct SHA1Context sha1;
24f05cddf9SRui Paulo #ifdef CONFIG_SHA256
25f05cddf9SRui Paulo 		struct sha256_state sha256;
26f05cddf9SRui Paulo #endif /* CONFIG_SHA256 */
27780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA384
28780fb4a2SCy Schubert 		struct sha384_state sha384;
29780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA384 */
30780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA512
31780fb4a2SCy Schubert 		struct sha512_state sha512;
32780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA512 */
3339beb93cSSam Leffler 	} u;
3439beb93cSSam Leffler 	u8 key[64];
3539beb93cSSam Leffler 	size_t key_len;
3639beb93cSSam Leffler };
3739beb93cSSam Leffler 
3839beb93cSSam Leffler 
crypto_hash_init(enum crypto_hash_alg alg,const u8 * key,size_t key_len)3939beb93cSSam Leffler struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
4039beb93cSSam Leffler 				      size_t key_len)
4139beb93cSSam Leffler {
4239beb93cSSam Leffler 	struct crypto_hash *ctx;
4339beb93cSSam Leffler 	u8 k_pad[64];
44f05cddf9SRui Paulo 	u8 tk[32];
4539beb93cSSam Leffler 	size_t i;
4639beb93cSSam Leffler 
4739beb93cSSam Leffler 	ctx = os_zalloc(sizeof(*ctx));
4839beb93cSSam Leffler 	if (ctx == NULL)
4939beb93cSSam Leffler 		return NULL;
5039beb93cSSam Leffler 
5139beb93cSSam Leffler 	ctx->alg = alg;
5239beb93cSSam Leffler 
5339beb93cSSam Leffler 	switch (alg) {
5439beb93cSSam Leffler 	case CRYPTO_HASH_ALG_MD5:
5539beb93cSSam Leffler 		MD5Init(&ctx->u.md5);
5639beb93cSSam Leffler 		break;
5739beb93cSSam Leffler 	case CRYPTO_HASH_ALG_SHA1:
5839beb93cSSam Leffler 		SHA1Init(&ctx->u.sha1);
5939beb93cSSam Leffler 		break;
60f05cddf9SRui Paulo #ifdef CONFIG_SHA256
61f05cddf9SRui Paulo 	case CRYPTO_HASH_ALG_SHA256:
62f05cddf9SRui Paulo 		sha256_init(&ctx->u.sha256);
63f05cddf9SRui Paulo 		break;
64f05cddf9SRui Paulo #endif /* CONFIG_SHA256 */
65780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA384
66780fb4a2SCy Schubert 	case CRYPTO_HASH_ALG_SHA384:
67780fb4a2SCy Schubert 		sha384_init(&ctx->u.sha384);
68780fb4a2SCy Schubert 		break;
69780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA384 */
70780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA512
71780fb4a2SCy Schubert 	case CRYPTO_HASH_ALG_SHA512:
72780fb4a2SCy Schubert 		sha512_init(&ctx->u.sha512);
73780fb4a2SCy Schubert 		break;
74780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA512 */
7539beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_MD5:
7639beb93cSSam Leffler 		if (key_len > sizeof(k_pad)) {
7739beb93cSSam Leffler 			MD5Init(&ctx->u.md5);
7839beb93cSSam Leffler 			MD5Update(&ctx->u.md5, key, key_len);
7939beb93cSSam Leffler 			MD5Final(tk, &ctx->u.md5);
8039beb93cSSam Leffler 			key = tk;
8139beb93cSSam Leffler 			key_len = 16;
8239beb93cSSam Leffler 		}
8339beb93cSSam Leffler 		os_memcpy(ctx->key, key, key_len);
8439beb93cSSam Leffler 		ctx->key_len = key_len;
8539beb93cSSam Leffler 
8639beb93cSSam Leffler 		os_memcpy(k_pad, key, key_len);
87f05cddf9SRui Paulo 		if (key_len < sizeof(k_pad))
8839beb93cSSam Leffler 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
8939beb93cSSam Leffler 		for (i = 0; i < sizeof(k_pad); i++)
9039beb93cSSam Leffler 			k_pad[i] ^= 0x36;
9139beb93cSSam Leffler 		MD5Init(&ctx->u.md5);
9239beb93cSSam Leffler 		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
9339beb93cSSam Leffler 		break;
9439beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_SHA1:
9539beb93cSSam Leffler 		if (key_len > sizeof(k_pad)) {
9639beb93cSSam Leffler 			SHA1Init(&ctx->u.sha1);
9739beb93cSSam Leffler 			SHA1Update(&ctx->u.sha1, key, key_len);
9839beb93cSSam Leffler 			SHA1Final(tk, &ctx->u.sha1);
9939beb93cSSam Leffler 			key = tk;
10039beb93cSSam Leffler 			key_len = 20;
10139beb93cSSam Leffler 		}
10239beb93cSSam Leffler 		os_memcpy(ctx->key, key, key_len);
10339beb93cSSam Leffler 		ctx->key_len = key_len;
10439beb93cSSam Leffler 
10539beb93cSSam Leffler 		os_memcpy(k_pad, key, key_len);
106f05cddf9SRui Paulo 		if (key_len < sizeof(k_pad))
10739beb93cSSam Leffler 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
10839beb93cSSam Leffler 		for (i = 0; i < sizeof(k_pad); i++)
10939beb93cSSam Leffler 			k_pad[i] ^= 0x36;
11039beb93cSSam Leffler 		SHA1Init(&ctx->u.sha1);
11139beb93cSSam Leffler 		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
11239beb93cSSam Leffler 		break;
113f05cddf9SRui Paulo #ifdef CONFIG_SHA256
114f05cddf9SRui Paulo 	case CRYPTO_HASH_ALG_HMAC_SHA256:
115f05cddf9SRui Paulo 		if (key_len > sizeof(k_pad)) {
116f05cddf9SRui Paulo 			sha256_init(&ctx->u.sha256);
117f05cddf9SRui Paulo 			sha256_process(&ctx->u.sha256, key, key_len);
118f05cddf9SRui Paulo 			sha256_done(&ctx->u.sha256, tk);
119f05cddf9SRui Paulo 			key = tk;
120f05cddf9SRui Paulo 			key_len = 32;
121f05cddf9SRui Paulo 		}
122f05cddf9SRui Paulo 		os_memcpy(ctx->key, key, key_len);
123f05cddf9SRui Paulo 		ctx->key_len = key_len;
124f05cddf9SRui Paulo 
125f05cddf9SRui Paulo 		os_memcpy(k_pad, key, key_len);
126f05cddf9SRui Paulo 		if (key_len < sizeof(k_pad))
127f05cddf9SRui Paulo 			os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
128f05cddf9SRui Paulo 		for (i = 0; i < sizeof(k_pad); i++)
129f05cddf9SRui Paulo 			k_pad[i] ^= 0x36;
130f05cddf9SRui Paulo 		sha256_init(&ctx->u.sha256);
131f05cddf9SRui Paulo 		sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
132f05cddf9SRui Paulo 		break;
133f05cddf9SRui Paulo #endif /* CONFIG_SHA256 */
13439beb93cSSam Leffler 	default:
13539beb93cSSam Leffler 		os_free(ctx);
13639beb93cSSam Leffler 		return NULL;
13739beb93cSSam Leffler 	}
13839beb93cSSam Leffler 
13939beb93cSSam Leffler 	return ctx;
14039beb93cSSam Leffler }
14139beb93cSSam Leffler 
14239beb93cSSam Leffler 
crypto_hash_update(struct crypto_hash * ctx,const u8 * data,size_t len)14339beb93cSSam Leffler void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
14439beb93cSSam Leffler {
14539beb93cSSam Leffler 	if (ctx == NULL)
14639beb93cSSam Leffler 		return;
14739beb93cSSam Leffler 
14839beb93cSSam Leffler 	switch (ctx->alg) {
14939beb93cSSam Leffler 	case CRYPTO_HASH_ALG_MD5:
15039beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_MD5:
15139beb93cSSam Leffler 		MD5Update(&ctx->u.md5, data, len);
15239beb93cSSam Leffler 		break;
15339beb93cSSam Leffler 	case CRYPTO_HASH_ALG_SHA1:
15439beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_SHA1:
15539beb93cSSam Leffler 		SHA1Update(&ctx->u.sha1, data, len);
15639beb93cSSam Leffler 		break;
157f05cddf9SRui Paulo #ifdef CONFIG_SHA256
158f05cddf9SRui Paulo 	case CRYPTO_HASH_ALG_SHA256:
159f05cddf9SRui Paulo 	case CRYPTO_HASH_ALG_HMAC_SHA256:
160f05cddf9SRui Paulo 		sha256_process(&ctx->u.sha256, data, len);
161f05cddf9SRui Paulo 		break;
162f05cddf9SRui Paulo #endif /* CONFIG_SHA256 */
163780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA384
164780fb4a2SCy Schubert 	case CRYPTO_HASH_ALG_SHA384:
165780fb4a2SCy Schubert 		sha384_process(&ctx->u.sha384, data, len);
166780fb4a2SCy Schubert 		break;
167780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA384 */
168780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA512
169780fb4a2SCy Schubert 	case CRYPTO_HASH_ALG_SHA512:
170780fb4a2SCy Schubert 		sha512_process(&ctx->u.sha512, data, len);
171780fb4a2SCy Schubert 		break;
172780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA512 */
173f05cddf9SRui Paulo 	default:
174f05cddf9SRui Paulo 		break;
17539beb93cSSam Leffler 	}
17639beb93cSSam Leffler }
17739beb93cSSam Leffler 
17839beb93cSSam Leffler 
crypto_hash_finish(struct crypto_hash * ctx,u8 * mac,size_t * len)17939beb93cSSam Leffler int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
18039beb93cSSam Leffler {
18139beb93cSSam Leffler 	u8 k_pad[64];
18239beb93cSSam Leffler 	size_t i;
18339beb93cSSam Leffler 
18439beb93cSSam Leffler 	if (ctx == NULL)
18539beb93cSSam Leffler 		return -2;
18639beb93cSSam Leffler 
18739beb93cSSam Leffler 	if (mac == NULL || len == NULL) {
18839beb93cSSam Leffler 		os_free(ctx);
18939beb93cSSam Leffler 		return 0;
19039beb93cSSam Leffler 	}
19139beb93cSSam Leffler 
19239beb93cSSam Leffler 	switch (ctx->alg) {
19339beb93cSSam Leffler 	case CRYPTO_HASH_ALG_MD5:
19439beb93cSSam Leffler 		if (*len < 16) {
19539beb93cSSam Leffler 			*len = 16;
19639beb93cSSam Leffler 			os_free(ctx);
19739beb93cSSam Leffler 			return -1;
19839beb93cSSam Leffler 		}
19939beb93cSSam Leffler 		*len = 16;
20039beb93cSSam Leffler 		MD5Final(mac, &ctx->u.md5);
20139beb93cSSam Leffler 		break;
20239beb93cSSam Leffler 	case CRYPTO_HASH_ALG_SHA1:
20339beb93cSSam Leffler 		if (*len < 20) {
20439beb93cSSam Leffler 			*len = 20;
20539beb93cSSam Leffler 			os_free(ctx);
20639beb93cSSam Leffler 			return -1;
20739beb93cSSam Leffler 		}
20839beb93cSSam Leffler 		*len = 20;
20939beb93cSSam Leffler 		SHA1Final(mac, &ctx->u.sha1);
21039beb93cSSam Leffler 		break;
211f05cddf9SRui Paulo #ifdef CONFIG_SHA256
212f05cddf9SRui Paulo 	case CRYPTO_HASH_ALG_SHA256:
213f05cddf9SRui Paulo 		if (*len < 32) {
214f05cddf9SRui Paulo 			*len = 32;
215f05cddf9SRui Paulo 			os_free(ctx);
216f05cddf9SRui Paulo 			return -1;
217f05cddf9SRui Paulo 		}
218f05cddf9SRui Paulo 		*len = 32;
219f05cddf9SRui Paulo 		sha256_done(&ctx->u.sha256, mac);
220f05cddf9SRui Paulo 		break;
221f05cddf9SRui Paulo #endif /* CONFIG_SHA256 */
222780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA384
223780fb4a2SCy Schubert 	case CRYPTO_HASH_ALG_SHA384:
224780fb4a2SCy Schubert 		if (*len < 48) {
225780fb4a2SCy Schubert 			*len = 48;
226780fb4a2SCy Schubert 			os_free(ctx);
227780fb4a2SCy Schubert 			return -1;
228780fb4a2SCy Schubert 		}
229780fb4a2SCy Schubert 		*len = 48;
230780fb4a2SCy Schubert 		sha384_done(&ctx->u.sha384, mac);
231780fb4a2SCy Schubert 		break;
232780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA384 */
233780fb4a2SCy Schubert #ifdef CONFIG_INTERNAL_SHA512
234780fb4a2SCy Schubert 	case CRYPTO_HASH_ALG_SHA512:
235780fb4a2SCy Schubert 		if (*len < 64) {
236780fb4a2SCy Schubert 			*len = 64;
237780fb4a2SCy Schubert 			os_free(ctx);
238780fb4a2SCy Schubert 			return -1;
239780fb4a2SCy Schubert 		}
240780fb4a2SCy Schubert 		*len = 64;
241780fb4a2SCy Schubert 		sha512_done(&ctx->u.sha512, mac);
242780fb4a2SCy Schubert 		break;
243780fb4a2SCy Schubert #endif /* CONFIG_INTERNAL_SHA512 */
24439beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_MD5:
24539beb93cSSam Leffler 		if (*len < 16) {
24639beb93cSSam Leffler 			*len = 16;
24739beb93cSSam Leffler 			os_free(ctx);
24839beb93cSSam Leffler 			return -1;
24939beb93cSSam Leffler 		}
25039beb93cSSam Leffler 		*len = 16;
25139beb93cSSam Leffler 
25239beb93cSSam Leffler 		MD5Final(mac, &ctx->u.md5);
25339beb93cSSam Leffler 
25439beb93cSSam Leffler 		os_memcpy(k_pad, ctx->key, ctx->key_len);
25539beb93cSSam Leffler 		os_memset(k_pad + ctx->key_len, 0,
25639beb93cSSam Leffler 			  sizeof(k_pad) - ctx->key_len);
25739beb93cSSam Leffler 		for (i = 0; i < sizeof(k_pad); i++)
25839beb93cSSam Leffler 			k_pad[i] ^= 0x5c;
25939beb93cSSam Leffler 		MD5Init(&ctx->u.md5);
26039beb93cSSam Leffler 		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
26139beb93cSSam Leffler 		MD5Update(&ctx->u.md5, mac, 16);
26239beb93cSSam Leffler 		MD5Final(mac, &ctx->u.md5);
26339beb93cSSam Leffler 		break;
26439beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_SHA1:
26539beb93cSSam Leffler 		if (*len < 20) {
26639beb93cSSam Leffler 			*len = 20;
26739beb93cSSam Leffler 			os_free(ctx);
26839beb93cSSam Leffler 			return -1;
26939beb93cSSam Leffler 		}
27039beb93cSSam Leffler 		*len = 20;
27139beb93cSSam Leffler 
27239beb93cSSam Leffler 		SHA1Final(mac, &ctx->u.sha1);
27339beb93cSSam Leffler 
27439beb93cSSam Leffler 		os_memcpy(k_pad, ctx->key, ctx->key_len);
27539beb93cSSam Leffler 		os_memset(k_pad + ctx->key_len, 0,
27639beb93cSSam Leffler 			  sizeof(k_pad) - ctx->key_len);
27739beb93cSSam Leffler 		for (i = 0; i < sizeof(k_pad); i++)
27839beb93cSSam Leffler 			k_pad[i] ^= 0x5c;
27939beb93cSSam Leffler 		SHA1Init(&ctx->u.sha1);
28039beb93cSSam Leffler 		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
28139beb93cSSam Leffler 		SHA1Update(&ctx->u.sha1, mac, 20);
28239beb93cSSam Leffler 		SHA1Final(mac, &ctx->u.sha1);
28339beb93cSSam Leffler 		break;
284f05cddf9SRui Paulo #ifdef CONFIG_SHA256
285f05cddf9SRui Paulo 	case CRYPTO_HASH_ALG_HMAC_SHA256:
286f05cddf9SRui Paulo 		if (*len < 32) {
287f05cddf9SRui Paulo 			*len = 32;
288f05cddf9SRui Paulo 			os_free(ctx);
289f05cddf9SRui Paulo 			return -1;
290f05cddf9SRui Paulo 		}
291f05cddf9SRui Paulo 		*len = 32;
292f05cddf9SRui Paulo 
293f05cddf9SRui Paulo 		sha256_done(&ctx->u.sha256, mac);
294f05cddf9SRui Paulo 
295f05cddf9SRui Paulo 		os_memcpy(k_pad, ctx->key, ctx->key_len);
296f05cddf9SRui Paulo 		os_memset(k_pad + ctx->key_len, 0,
297f05cddf9SRui Paulo 			  sizeof(k_pad) - ctx->key_len);
298f05cddf9SRui Paulo 		for (i = 0; i < sizeof(k_pad); i++)
299f05cddf9SRui Paulo 			k_pad[i] ^= 0x5c;
300f05cddf9SRui Paulo 		sha256_init(&ctx->u.sha256);
301f05cddf9SRui Paulo 		sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
302f05cddf9SRui Paulo 		sha256_process(&ctx->u.sha256, mac, 32);
303f05cddf9SRui Paulo 		sha256_done(&ctx->u.sha256, mac);
304f05cddf9SRui Paulo 		break;
305f05cddf9SRui Paulo #endif /* CONFIG_SHA256 */
306f05cddf9SRui Paulo 	default:
307f05cddf9SRui Paulo 		os_free(ctx);
308f05cddf9SRui Paulo 		return -1;
30939beb93cSSam Leffler 	}
31039beb93cSSam Leffler 
31139beb93cSSam Leffler 	os_free(ctx);
31239beb93cSSam Leffler 
3134bc52338SCy Schubert 	if (TEST_FAIL())
3144bc52338SCy Schubert 		return -1;
3154bc52338SCy Schubert 
31639beb93cSSam Leffler 	return 0;
31739beb93cSSam Leffler }
31839beb93cSSam Leffler 
31939beb93cSSam Leffler 
crypto_global_init(void)32039beb93cSSam Leffler int crypto_global_init(void)
32139beb93cSSam Leffler {
32239beb93cSSam Leffler 	return 0;
32339beb93cSSam Leffler }
32439beb93cSSam Leffler 
32539beb93cSSam Leffler 
crypto_global_deinit(void)32639beb93cSSam Leffler void crypto_global_deinit(void)
32739beb93cSSam Leffler {
32839beb93cSSam Leffler }
329*a90b9d01SCy Schubert 
330*a90b9d01SCy Schubert 
crypto_unload(void)331*a90b9d01SCy Schubert void crypto_unload(void)
332*a90b9d01SCy Schubert {
333*a90b9d01SCy Schubert }
334