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
19struct 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
39struct 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
143void 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
179int 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	if (TEST_FAIL())
314		return -1;
315
316	return 0;
317}
318
319
320int crypto_global_init(void)
321{
322	return 0;
323}
324
325
326void crypto_global_deinit(void)
327{
328}
329