xref: /freebsd/contrib/wpa/src/crypto/crypto_internal.c (revision e28a4053b110e06768631ac8401ed4a3c05e68a5)
139beb93cSSam Leffler /*
2*e28a4053SRui Paulo  * Crypto wrapper for internal crypto implementation
3*e28a4053SRui Paulo  * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
439beb93cSSam Leffler  *
539beb93cSSam Leffler  * This program is free software; you can redistribute it and/or modify
639beb93cSSam Leffler  * it under the terms of the GNU General Public License version 2 as
739beb93cSSam Leffler  * published by the Free Software Foundation.
839beb93cSSam Leffler  *
939beb93cSSam Leffler  * Alternatively, this software may be distributed under the terms of BSD
1039beb93cSSam Leffler  * license.
1139beb93cSSam Leffler  *
1239beb93cSSam Leffler  * See README and COPYING for more details.
1339beb93cSSam Leffler  */
1439beb93cSSam Leffler 
1539beb93cSSam Leffler #include "includes.h"
1639beb93cSSam Leffler 
1739beb93cSSam Leffler #include "common.h"
1839beb93cSSam Leffler #include "crypto.h"
19*e28a4053SRui Paulo #include "sha1_i.h"
20*e28a4053SRui Paulo #include "md5_i.h"
2139beb93cSSam Leffler 
2239beb93cSSam Leffler struct crypto_hash {
2339beb93cSSam Leffler 	enum crypto_hash_alg alg;
2439beb93cSSam Leffler 	union {
2539beb93cSSam Leffler 		struct MD5Context md5;
2639beb93cSSam Leffler 		struct SHA1Context sha1;
2739beb93cSSam Leffler 	} u;
2839beb93cSSam Leffler 	u8 key[64];
2939beb93cSSam Leffler 	size_t key_len;
3039beb93cSSam Leffler };
3139beb93cSSam Leffler 
3239beb93cSSam Leffler 
3339beb93cSSam Leffler struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
3439beb93cSSam Leffler 				      size_t key_len)
3539beb93cSSam Leffler {
3639beb93cSSam Leffler 	struct crypto_hash *ctx;
3739beb93cSSam Leffler 	u8 k_pad[64];
3839beb93cSSam Leffler 	u8 tk[20];
3939beb93cSSam Leffler 	size_t i;
4039beb93cSSam Leffler 
4139beb93cSSam Leffler 	ctx = os_zalloc(sizeof(*ctx));
4239beb93cSSam Leffler 	if (ctx == NULL)
4339beb93cSSam Leffler 		return NULL;
4439beb93cSSam Leffler 
4539beb93cSSam Leffler 	ctx->alg = alg;
4639beb93cSSam Leffler 
4739beb93cSSam Leffler 	switch (alg) {
4839beb93cSSam Leffler 	case CRYPTO_HASH_ALG_MD5:
4939beb93cSSam Leffler 		MD5Init(&ctx->u.md5);
5039beb93cSSam Leffler 		break;
5139beb93cSSam Leffler 	case CRYPTO_HASH_ALG_SHA1:
5239beb93cSSam Leffler 		SHA1Init(&ctx->u.sha1);
5339beb93cSSam Leffler 		break;
5439beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_MD5:
5539beb93cSSam Leffler 		if (key_len > sizeof(k_pad)) {
5639beb93cSSam Leffler 			MD5Init(&ctx->u.md5);
5739beb93cSSam Leffler 			MD5Update(&ctx->u.md5, key, key_len);
5839beb93cSSam Leffler 			MD5Final(tk, &ctx->u.md5);
5939beb93cSSam Leffler 			key = tk;
6039beb93cSSam Leffler 			key_len = 16;
6139beb93cSSam Leffler 		}
6239beb93cSSam Leffler 		os_memcpy(ctx->key, key, key_len);
6339beb93cSSam Leffler 		ctx->key_len = key_len;
6439beb93cSSam Leffler 
6539beb93cSSam Leffler 		os_memcpy(k_pad, key, key_len);
6639beb93cSSam Leffler 		os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
6739beb93cSSam Leffler 		for (i = 0; i < sizeof(k_pad); i++)
6839beb93cSSam Leffler 			k_pad[i] ^= 0x36;
6939beb93cSSam Leffler 		MD5Init(&ctx->u.md5);
7039beb93cSSam Leffler 		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
7139beb93cSSam Leffler 		break;
7239beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_SHA1:
7339beb93cSSam Leffler 		if (key_len > sizeof(k_pad)) {
7439beb93cSSam Leffler 			SHA1Init(&ctx->u.sha1);
7539beb93cSSam Leffler 			SHA1Update(&ctx->u.sha1, key, key_len);
7639beb93cSSam Leffler 			SHA1Final(tk, &ctx->u.sha1);
7739beb93cSSam Leffler 			key = tk;
7839beb93cSSam Leffler 			key_len = 20;
7939beb93cSSam Leffler 		}
8039beb93cSSam Leffler 		os_memcpy(ctx->key, key, key_len);
8139beb93cSSam Leffler 		ctx->key_len = key_len;
8239beb93cSSam Leffler 
8339beb93cSSam Leffler 		os_memcpy(k_pad, key, key_len);
8439beb93cSSam Leffler 		os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
8539beb93cSSam Leffler 		for (i = 0; i < sizeof(k_pad); i++)
8639beb93cSSam Leffler 			k_pad[i] ^= 0x36;
8739beb93cSSam Leffler 		SHA1Init(&ctx->u.sha1);
8839beb93cSSam Leffler 		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
8939beb93cSSam Leffler 		break;
9039beb93cSSam Leffler 	default:
9139beb93cSSam Leffler 		os_free(ctx);
9239beb93cSSam Leffler 		return NULL;
9339beb93cSSam Leffler 	}
9439beb93cSSam Leffler 
9539beb93cSSam Leffler 	return ctx;
9639beb93cSSam Leffler }
9739beb93cSSam Leffler 
9839beb93cSSam Leffler 
9939beb93cSSam Leffler void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
10039beb93cSSam Leffler {
10139beb93cSSam Leffler 	if (ctx == NULL)
10239beb93cSSam Leffler 		return;
10339beb93cSSam Leffler 
10439beb93cSSam Leffler 	switch (ctx->alg) {
10539beb93cSSam Leffler 	case CRYPTO_HASH_ALG_MD5:
10639beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_MD5:
10739beb93cSSam Leffler 		MD5Update(&ctx->u.md5, data, len);
10839beb93cSSam Leffler 		break;
10939beb93cSSam Leffler 	case CRYPTO_HASH_ALG_SHA1:
11039beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_SHA1:
11139beb93cSSam Leffler 		SHA1Update(&ctx->u.sha1, data, len);
11239beb93cSSam Leffler 		break;
11339beb93cSSam Leffler 	}
11439beb93cSSam Leffler }
11539beb93cSSam Leffler 
11639beb93cSSam Leffler 
11739beb93cSSam Leffler int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
11839beb93cSSam Leffler {
11939beb93cSSam Leffler 	u8 k_pad[64];
12039beb93cSSam Leffler 	size_t i;
12139beb93cSSam Leffler 
12239beb93cSSam Leffler 	if (ctx == NULL)
12339beb93cSSam Leffler 		return -2;
12439beb93cSSam Leffler 
12539beb93cSSam Leffler 	if (mac == NULL || len == NULL) {
12639beb93cSSam Leffler 		os_free(ctx);
12739beb93cSSam Leffler 		return 0;
12839beb93cSSam Leffler 	}
12939beb93cSSam Leffler 
13039beb93cSSam Leffler 	switch (ctx->alg) {
13139beb93cSSam Leffler 	case CRYPTO_HASH_ALG_MD5:
13239beb93cSSam Leffler 		if (*len < 16) {
13339beb93cSSam Leffler 			*len = 16;
13439beb93cSSam Leffler 			os_free(ctx);
13539beb93cSSam Leffler 			return -1;
13639beb93cSSam Leffler 		}
13739beb93cSSam Leffler 		*len = 16;
13839beb93cSSam Leffler 		MD5Final(mac, &ctx->u.md5);
13939beb93cSSam Leffler 		break;
14039beb93cSSam Leffler 	case CRYPTO_HASH_ALG_SHA1:
14139beb93cSSam Leffler 		if (*len < 20) {
14239beb93cSSam Leffler 			*len = 20;
14339beb93cSSam Leffler 			os_free(ctx);
14439beb93cSSam Leffler 			return -1;
14539beb93cSSam Leffler 		}
14639beb93cSSam Leffler 		*len = 20;
14739beb93cSSam Leffler 		SHA1Final(mac, &ctx->u.sha1);
14839beb93cSSam Leffler 		break;
14939beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_MD5:
15039beb93cSSam Leffler 		if (*len < 16) {
15139beb93cSSam Leffler 			*len = 16;
15239beb93cSSam Leffler 			os_free(ctx);
15339beb93cSSam Leffler 			return -1;
15439beb93cSSam Leffler 		}
15539beb93cSSam Leffler 		*len = 16;
15639beb93cSSam Leffler 
15739beb93cSSam Leffler 		MD5Final(mac, &ctx->u.md5);
15839beb93cSSam Leffler 
15939beb93cSSam Leffler 		os_memcpy(k_pad, ctx->key, ctx->key_len);
16039beb93cSSam Leffler 		os_memset(k_pad + ctx->key_len, 0,
16139beb93cSSam Leffler 			  sizeof(k_pad) - ctx->key_len);
16239beb93cSSam Leffler 		for (i = 0; i < sizeof(k_pad); i++)
16339beb93cSSam Leffler 			k_pad[i] ^= 0x5c;
16439beb93cSSam Leffler 		MD5Init(&ctx->u.md5);
16539beb93cSSam Leffler 		MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
16639beb93cSSam Leffler 		MD5Update(&ctx->u.md5, mac, 16);
16739beb93cSSam Leffler 		MD5Final(mac, &ctx->u.md5);
16839beb93cSSam Leffler 		break;
16939beb93cSSam Leffler 	case CRYPTO_HASH_ALG_HMAC_SHA1:
17039beb93cSSam Leffler 		if (*len < 20) {
17139beb93cSSam Leffler 			*len = 20;
17239beb93cSSam Leffler 			os_free(ctx);
17339beb93cSSam Leffler 			return -1;
17439beb93cSSam Leffler 		}
17539beb93cSSam Leffler 		*len = 20;
17639beb93cSSam Leffler 
17739beb93cSSam Leffler 		SHA1Final(mac, &ctx->u.sha1);
17839beb93cSSam Leffler 
17939beb93cSSam Leffler 		os_memcpy(k_pad, ctx->key, ctx->key_len);
18039beb93cSSam Leffler 		os_memset(k_pad + ctx->key_len, 0,
18139beb93cSSam Leffler 			  sizeof(k_pad) - ctx->key_len);
18239beb93cSSam Leffler 		for (i = 0; i < sizeof(k_pad); i++)
18339beb93cSSam Leffler 			k_pad[i] ^= 0x5c;
18439beb93cSSam Leffler 		SHA1Init(&ctx->u.sha1);
18539beb93cSSam Leffler 		SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
18639beb93cSSam Leffler 		SHA1Update(&ctx->u.sha1, mac, 20);
18739beb93cSSam Leffler 		SHA1Final(mac, &ctx->u.sha1);
18839beb93cSSam Leffler 		break;
18939beb93cSSam Leffler 	}
19039beb93cSSam Leffler 
19139beb93cSSam Leffler 	os_free(ctx);
19239beb93cSSam Leffler 
19339beb93cSSam Leffler 	return 0;
19439beb93cSSam Leffler }
19539beb93cSSam Leffler 
19639beb93cSSam Leffler 
19739beb93cSSam Leffler int crypto_global_init(void)
19839beb93cSSam Leffler {
19939beb93cSSam Leffler 	return 0;
20039beb93cSSam Leffler }
20139beb93cSSam Leffler 
20239beb93cSSam Leffler 
20339beb93cSSam Leffler void crypto_global_deinit(void)
20439beb93cSSam Leffler {
20539beb93cSSam Leffler }
206