]>
Commit | Line | Data |
---|---|---|
6fc6879b | 1 | /* |
be473f3f | 2 | * Crypto wrapper for internal crypto implementation |
dcff088d | 3 | * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi> |
6fc6879b | 4 | * |
0f3d578e JM |
5 | * This software may be distributed under the terms of the BSD license. |
6 | * See README for more details. | |
6fc6879b JM |
7 | */ |
8 | ||
9 | #include "includes.h" | |
10 | ||
11 | #include "common.h" | |
12 | #include "crypto.h" | |
dcff088d | 13 | #include "sha256_i.h" |
c0acec39 JM |
14 | #include "sha384_i.h" |
15 | #include "sha512_i.h" | |
6b5c4c33 JB |
16 | #include "sha1_i.h" |
17 | #include "md5_i.h" | |
6fc6879b | 18 | |
6fc6879b JM |
19 | struct crypto_hash { |
20 | enum crypto_hash_alg alg; | |
21 | union { | |
22 | struct MD5Context md5; | |
23 | struct SHA1Context sha1; | |
dcff088d JM |
24 | #ifdef CONFIG_SHA256 |
25 | struct sha256_state sha256; | |
26 | #endif /* CONFIG_SHA256 */ | |
c0acec39 JM |
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 */ | |
6fc6879b JM |
33 | } u; |
34 | u8 key[64]; | |
35 | size_t key_len; | |
36 | }; | |
37 | ||
38 | ||
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]; | |
dcff088d | 44 | u8 tk[32]; |
6fc6879b JM |
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; | |
dcff088d JM |
60 | #ifdef CONFIG_SHA256 |
61 | case CRYPTO_HASH_ALG_SHA256: | |
62 | sha256_init(&ctx->u.sha256); | |
63 | break; | |
64 | #endif /* CONFIG_SHA256 */ | |
c0acec39 JM |
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 */ | |
6fc6879b JM |
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); | |
911e10ea JM |
87 | if (key_len < sizeof(k_pad)) |
88 | os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); | |
6fc6879b JM |
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); | |
8f2e2e36 JM |
106 | if (key_len < sizeof(k_pad)) |
107 | os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len); | |
6fc6879b JM |
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; | |
dcff088d JM |
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 */ | |
6fc6879b JM |
134 | default: |
135 | os_free(ctx); | |
136 | return NULL; | |
137 | } | |
138 | ||
139 | return ctx; | |
140 | } | |
141 | ||
142 | ||
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; | |
dcff088d JM |
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 */ | |
c0acec39 JM |
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 */ | |
dcff088d JM |
173 | default: |
174 | break; | |
6fc6879b JM |
175 | } |
176 | } | |
177 | ||
178 | ||
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; | |
dcff088d JM |
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 */ | |
c0acec39 JM |
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 */ | |
6fc6879b JM |
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; | |
dcff088d JM |
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; | |
6fc6879b JM |
309 | } |
310 | ||
311 | os_free(ctx); | |
312 | ||
52b1cb5d JM |
313 | if (TEST_FAIL()) |
314 | return -1; | |
315 | ||
6fc6879b JM |
316 | return 0; |
317 | } | |
318 | ||
319 | ||
6fc6879b JM |
320 | int crypto_global_init(void) |
321 | { | |
322 | return 0; | |
323 | } | |
324 | ||
325 | ||
326 | void crypto_global_deinit(void) | |
327 | { | |
328 | } |