xref: /dragonfly/contrib/wpa_supplicant/src/crypto/crypto_internal.c (revision 3a84a4273475ed07d0ab1c2dfeffdfedef35d9cd)
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           if (TEST_FAIL())
314                     return -1;
315 
316           return 0;
317 }
318 
319 
crypto_global_init(void)320 int crypto_global_init(void)
321 {
322           return 0;
323 }
324 
325 
crypto_global_deinit(void)326 void crypto_global_deinit(void)
327 {
328 }
329