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