blob: f3602dac346ea3cd6e9db7cf037a346d19c7e486 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * Crypto wrapper for internal crypto implementation
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003 * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#include "common.h"
12#include "crypto.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080013#include "sha256_i.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070014#include "sha1_i.h"
15#include "md5_i.h"
16
17struct crypto_hash {
18 enum crypto_hash_alg alg;
19 union {
20 struct MD5Context md5;
21 struct SHA1Context sha1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080022#ifdef CONFIG_SHA256
23 struct sha256_state sha256;
24#endif /* CONFIG_SHA256 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025 } u;
26 u8 key[64];
27 size_t key_len;
28};
29
30
31struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
32 size_t key_len)
33{
34 struct crypto_hash *ctx;
35 u8 k_pad[64];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080036 u8 tk[32];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037 size_t i;
38
39 ctx = os_zalloc(sizeof(*ctx));
40 if (ctx == NULL)
41 return NULL;
42
43 ctx->alg = alg;
44
45 switch (alg) {
46 case CRYPTO_HASH_ALG_MD5:
47 MD5Init(&ctx->u.md5);
48 break;
49 case CRYPTO_HASH_ALG_SHA1:
50 SHA1Init(&ctx->u.sha1);
51 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080052#ifdef CONFIG_SHA256
53 case CRYPTO_HASH_ALG_SHA256:
54 sha256_init(&ctx->u.sha256);
55 break;
56#endif /* CONFIG_SHA256 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070057 case CRYPTO_HASH_ALG_HMAC_MD5:
58 if (key_len > sizeof(k_pad)) {
59 MD5Init(&ctx->u.md5);
60 MD5Update(&ctx->u.md5, key, key_len);
61 MD5Final(tk, &ctx->u.md5);
62 key = tk;
63 key_len = 16;
64 }
65 os_memcpy(ctx->key, key, key_len);
66 ctx->key_len = key_len;
67
68 os_memcpy(k_pad, key, key_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080069 if (key_len < sizeof(k_pad))
70 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070071 for (i = 0; i < sizeof(k_pad); i++)
72 k_pad[i] ^= 0x36;
73 MD5Init(&ctx->u.md5);
74 MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
75 break;
76 case CRYPTO_HASH_ALG_HMAC_SHA1:
77 if (key_len > sizeof(k_pad)) {
78 SHA1Init(&ctx->u.sha1);
79 SHA1Update(&ctx->u.sha1, key, key_len);
80 SHA1Final(tk, &ctx->u.sha1);
81 key = tk;
82 key_len = 20;
83 }
84 os_memcpy(ctx->key, key, key_len);
85 ctx->key_len = key_len;
86
87 os_memcpy(k_pad, key, key_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080088 if (key_len < sizeof(k_pad))
89 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070090 for (i = 0; i < sizeof(k_pad); i++)
91 k_pad[i] ^= 0x36;
92 SHA1Init(&ctx->u.sha1);
93 SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
94 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080095#ifdef CONFIG_SHA256
96 case CRYPTO_HASH_ALG_HMAC_SHA256:
97 if (key_len > sizeof(k_pad)) {
98 sha256_init(&ctx->u.sha256);
99 sha256_process(&ctx->u.sha256, key, key_len);
100 sha256_done(&ctx->u.sha256, tk);
101 key = tk;
102 key_len = 32;
103 }
104 os_memcpy(ctx->key, key, key_len);
105 ctx->key_len = key_len;
106
107 os_memcpy(k_pad, key, key_len);
108 if (key_len < sizeof(k_pad))
109 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
110 for (i = 0; i < sizeof(k_pad); i++)
111 k_pad[i] ^= 0x36;
112 sha256_init(&ctx->u.sha256);
113 sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
114 break;
115#endif /* CONFIG_SHA256 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700116 default:
117 os_free(ctx);
118 return NULL;
119 }
120
121 return ctx;
122}
123
124
125void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
126{
127 if (ctx == NULL)
128 return;
129
130 switch (ctx->alg) {
131 case CRYPTO_HASH_ALG_MD5:
132 case CRYPTO_HASH_ALG_HMAC_MD5:
133 MD5Update(&ctx->u.md5, data, len);
134 break;
135 case CRYPTO_HASH_ALG_SHA1:
136 case CRYPTO_HASH_ALG_HMAC_SHA1:
137 SHA1Update(&ctx->u.sha1, data, len);
138 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800139#ifdef CONFIG_SHA256
140 case CRYPTO_HASH_ALG_SHA256:
141 case CRYPTO_HASH_ALG_HMAC_SHA256:
142 sha256_process(&ctx->u.sha256, data, len);
143 break;
144#endif /* CONFIG_SHA256 */
145 default:
146 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700147 }
148}
149
150
151int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
152{
153 u8 k_pad[64];
154 size_t i;
155
156 if (ctx == NULL)
157 return -2;
158
159 if (mac == NULL || len == NULL) {
160 os_free(ctx);
161 return 0;
162 }
163
164 switch (ctx->alg) {
165 case CRYPTO_HASH_ALG_MD5:
166 if (*len < 16) {
167 *len = 16;
168 os_free(ctx);
169 return -1;
170 }
171 *len = 16;
172 MD5Final(mac, &ctx->u.md5);
173 break;
174 case CRYPTO_HASH_ALG_SHA1:
175 if (*len < 20) {
176 *len = 20;
177 os_free(ctx);
178 return -1;
179 }
180 *len = 20;
181 SHA1Final(mac, &ctx->u.sha1);
182 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800183#ifdef CONFIG_SHA256
184 case CRYPTO_HASH_ALG_SHA256:
185 if (*len < 32) {
186 *len = 32;
187 os_free(ctx);
188 return -1;
189 }
190 *len = 32;
191 sha256_done(&ctx->u.sha256, mac);
192 break;
193#endif /* CONFIG_SHA256 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700194 case CRYPTO_HASH_ALG_HMAC_MD5:
195 if (*len < 16) {
196 *len = 16;
197 os_free(ctx);
198 return -1;
199 }
200 *len = 16;
201
202 MD5Final(mac, &ctx->u.md5);
203
204 os_memcpy(k_pad, ctx->key, ctx->key_len);
205 os_memset(k_pad + ctx->key_len, 0,
206 sizeof(k_pad) - ctx->key_len);
207 for (i = 0; i < sizeof(k_pad); i++)
208 k_pad[i] ^= 0x5c;
209 MD5Init(&ctx->u.md5);
210 MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
211 MD5Update(&ctx->u.md5, mac, 16);
212 MD5Final(mac, &ctx->u.md5);
213 break;
214 case CRYPTO_HASH_ALG_HMAC_SHA1:
215 if (*len < 20) {
216 *len = 20;
217 os_free(ctx);
218 return -1;
219 }
220 *len = 20;
221
222 SHA1Final(mac, &ctx->u.sha1);
223
224 os_memcpy(k_pad, ctx->key, ctx->key_len);
225 os_memset(k_pad + ctx->key_len, 0,
226 sizeof(k_pad) - ctx->key_len);
227 for (i = 0; i < sizeof(k_pad); i++)
228 k_pad[i] ^= 0x5c;
229 SHA1Init(&ctx->u.sha1);
230 SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
231 SHA1Update(&ctx->u.sha1, mac, 20);
232 SHA1Final(mac, &ctx->u.sha1);
233 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800234#ifdef CONFIG_SHA256
235 case CRYPTO_HASH_ALG_HMAC_SHA256:
236 if (*len < 32) {
237 *len = 32;
238 os_free(ctx);
239 return -1;
240 }
241 *len = 32;
242
243 sha256_done(&ctx->u.sha256, mac);
244
245 os_memcpy(k_pad, ctx->key, ctx->key_len);
246 os_memset(k_pad + ctx->key_len, 0,
247 sizeof(k_pad) - ctx->key_len);
248 for (i = 0; i < sizeof(k_pad); i++)
249 k_pad[i] ^= 0x5c;
250 sha256_init(&ctx->u.sha256);
251 sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
252 sha256_process(&ctx->u.sha256, mac, 32);
253 sha256_done(&ctx->u.sha256, mac);
254 break;
255#endif /* CONFIG_SHA256 */
256 default:
257 os_free(ctx);
258 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700259 }
260
261 os_free(ctx);
262
263 return 0;
264}
265
266
267int crypto_global_init(void)
268{
269 return 0;
270}
271
272
273void crypto_global_deinit(void)
274{
275}