Updated to hostap_2_6
[mech_eap.git] / libeap / src / crypto / crypto_internal.c
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
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
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
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
317 int crypto_global_init(void)
318 {
319         return 0;
320 }
321
322
323 void crypto_global_deinit(void)
324 {
325 }