]> git.ipfire.org Git - thirdparty/hostap.git/blame - src/crypto/crypto_internal.c
tests: crypto_hash_finish() failure in eap_pwd_kdf()
[thirdparty/hostap.git] / src / crypto / crypto_internal.c
CommitLineData
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
19struct 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
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];
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
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;
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
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;
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
320int crypto_global_init(void)
321{
322 return 0;
323}
324
325
326void crypto_global_deinit(void)
327{
328}