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
crypto_hash_init(enum crypto_hash_alg alg,const u8 * key,size_t key_len)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
crypto_hash_update(struct crypto_hash * ctx,const u8 * data,size_t len)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
crypto_hash_finish(struct crypto_hash * ctx,u8 * mac,size_t * len)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
crypto_global_init(void)317 int crypto_global_init(void)
318 {
319 return 0;
320 }
321
322
crypto_global_deinit(void)323 void crypto_global_deinit(void)
324 {
325 }
326