blob: 9362fe10831568c74199c42db331cee93164ce3d [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 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "includes.h"
16
17#include "common.h"
18#include "crypto.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080019#include "sha256_i.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070020#include "sha1_i.h"
21#include "md5_i.h"
22
23struct crypto_hash {
24 enum crypto_hash_alg alg;
25 union {
26 struct MD5Context md5;
27 struct SHA1Context sha1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080028#ifdef CONFIG_SHA256
29 struct sha256_state sha256;
30#endif /* CONFIG_SHA256 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070031 } u;
32 u8 key[64];
33 size_t key_len;
34};
35
36
37struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
38 size_t key_len)
39{
40 struct crypto_hash *ctx;
41 u8 k_pad[64];
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080042 u8 tk[32];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070043 size_t i;
44
45 ctx = os_zalloc(sizeof(*ctx));
46 if (ctx == NULL)
47 return NULL;
48
49 ctx->alg = alg;
50
51 switch (alg) {
52 case CRYPTO_HASH_ALG_MD5:
53 MD5Init(&ctx->u.md5);
54 break;
55 case CRYPTO_HASH_ALG_SHA1:
56 SHA1Init(&ctx->u.sha1);
57 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080058#ifdef CONFIG_SHA256
59 case CRYPTO_HASH_ALG_SHA256:
60 sha256_init(&ctx->u.sha256);
61 break;
62#endif /* CONFIG_SHA256 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070063 case CRYPTO_HASH_ALG_HMAC_MD5:
64 if (key_len > sizeof(k_pad)) {
65 MD5Init(&ctx->u.md5);
66 MD5Update(&ctx->u.md5, key, key_len);
67 MD5Final(tk, &ctx->u.md5);
68 key = tk;
69 key_len = 16;
70 }
71 os_memcpy(ctx->key, key, key_len);
72 ctx->key_len = key_len;
73
74 os_memcpy(k_pad, key, key_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080075 if (key_len < sizeof(k_pad))
76 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070077 for (i = 0; i < sizeof(k_pad); i++)
78 k_pad[i] ^= 0x36;
79 MD5Init(&ctx->u.md5);
80 MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
81 break;
82 case CRYPTO_HASH_ALG_HMAC_SHA1:
83 if (key_len > sizeof(k_pad)) {
84 SHA1Init(&ctx->u.sha1);
85 SHA1Update(&ctx->u.sha1, key, key_len);
86 SHA1Final(tk, &ctx->u.sha1);
87 key = tk;
88 key_len = 20;
89 }
90 os_memcpy(ctx->key, key, key_len);
91 ctx->key_len = key_len;
92
93 os_memcpy(k_pad, key, key_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080094 if (key_len < sizeof(k_pad))
95 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096 for (i = 0; i < sizeof(k_pad); i++)
97 k_pad[i] ^= 0x36;
98 SHA1Init(&ctx->u.sha1);
99 SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
100 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800101#ifdef CONFIG_SHA256
102 case CRYPTO_HASH_ALG_HMAC_SHA256:
103 if (key_len > sizeof(k_pad)) {
104 sha256_init(&ctx->u.sha256);
105 sha256_process(&ctx->u.sha256, key, key_len);
106 sha256_done(&ctx->u.sha256, tk);
107 key = tk;
108 key_len = 32;
109 }
110 os_memcpy(ctx->key, key, key_len);
111 ctx->key_len = key_len;
112
113 os_memcpy(k_pad, key, key_len);
114 if (key_len < sizeof(k_pad))
115 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
116 for (i = 0; i < sizeof(k_pad); i++)
117 k_pad[i] ^= 0x36;
118 sha256_init(&ctx->u.sha256);
119 sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
120 break;
121#endif /* CONFIG_SHA256 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700122 default:
123 os_free(ctx);
124 return NULL;
125 }
126
127 return ctx;
128}
129
130
131void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
132{
133 if (ctx == NULL)
134 return;
135
136 switch (ctx->alg) {
137 case CRYPTO_HASH_ALG_MD5:
138 case CRYPTO_HASH_ALG_HMAC_MD5:
139 MD5Update(&ctx->u.md5, data, len);
140 break;
141 case CRYPTO_HASH_ALG_SHA1:
142 case CRYPTO_HASH_ALG_HMAC_SHA1:
143 SHA1Update(&ctx->u.sha1, data, len);
144 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800145#ifdef CONFIG_SHA256
146 case CRYPTO_HASH_ALG_SHA256:
147 case CRYPTO_HASH_ALG_HMAC_SHA256:
148 sha256_process(&ctx->u.sha256, data, len);
149 break;
150#endif /* CONFIG_SHA256 */
151 default:
152 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700153 }
154}
155
156
157int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
158{
159 u8 k_pad[64];
160 size_t i;
161
162 if (ctx == NULL)
163 return -2;
164
165 if (mac == NULL || len == NULL) {
166 os_free(ctx);
167 return 0;
168 }
169
170 switch (ctx->alg) {
171 case CRYPTO_HASH_ALG_MD5:
172 if (*len < 16) {
173 *len = 16;
174 os_free(ctx);
175 return -1;
176 }
177 *len = 16;
178 MD5Final(mac, &ctx->u.md5);
179 break;
180 case CRYPTO_HASH_ALG_SHA1:
181 if (*len < 20) {
182 *len = 20;
183 os_free(ctx);
184 return -1;
185 }
186 *len = 20;
187 SHA1Final(mac, &ctx->u.sha1);
188 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800189#ifdef CONFIG_SHA256
190 case CRYPTO_HASH_ALG_SHA256:
191 if (*len < 32) {
192 *len = 32;
193 os_free(ctx);
194 return -1;
195 }
196 *len = 32;
197 sha256_done(&ctx->u.sha256, mac);
198 break;
199#endif /* CONFIG_SHA256 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700200 case CRYPTO_HASH_ALG_HMAC_MD5:
201 if (*len < 16) {
202 *len = 16;
203 os_free(ctx);
204 return -1;
205 }
206 *len = 16;
207
208 MD5Final(mac, &ctx->u.md5);
209
210 os_memcpy(k_pad, ctx->key, ctx->key_len);
211 os_memset(k_pad + ctx->key_len, 0,
212 sizeof(k_pad) - ctx->key_len);
213 for (i = 0; i < sizeof(k_pad); i++)
214 k_pad[i] ^= 0x5c;
215 MD5Init(&ctx->u.md5);
216 MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
217 MD5Update(&ctx->u.md5, mac, 16);
218 MD5Final(mac, &ctx->u.md5);
219 break;
220 case CRYPTO_HASH_ALG_HMAC_SHA1:
221 if (*len < 20) {
222 *len = 20;
223 os_free(ctx);
224 return -1;
225 }
226 *len = 20;
227
228 SHA1Final(mac, &ctx->u.sha1);
229
230 os_memcpy(k_pad, ctx->key, ctx->key_len);
231 os_memset(k_pad + ctx->key_len, 0,
232 sizeof(k_pad) - ctx->key_len);
233 for (i = 0; i < sizeof(k_pad); i++)
234 k_pad[i] ^= 0x5c;
235 SHA1Init(&ctx->u.sha1);
236 SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
237 SHA1Update(&ctx->u.sha1, mac, 20);
238 SHA1Final(mac, &ctx->u.sha1);
239 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800240#ifdef CONFIG_SHA256
241 case CRYPTO_HASH_ALG_HMAC_SHA256:
242 if (*len < 32) {
243 *len = 32;
244 os_free(ctx);
245 return -1;
246 }
247 *len = 32;
248
249 sha256_done(&ctx->u.sha256, mac);
250
251 os_memcpy(k_pad, ctx->key, ctx->key_len);
252 os_memset(k_pad + ctx->key_len, 0,
253 sizeof(k_pad) - ctx->key_len);
254 for (i = 0; i < sizeof(k_pad); i++)
255 k_pad[i] ^= 0x5c;
256 sha256_init(&ctx->u.sha256);
257 sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
258 sha256_process(&ctx->u.sha256, mac, 32);
259 sha256_done(&ctx->u.sha256, mac);
260 break;
261#endif /* CONFIG_SHA256 */
262 default:
263 os_free(ctx);
264 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700265 }
266
267 os_free(ctx);
268
269 return 0;
270}
271
272
273int crypto_global_init(void)
274{
275 return 0;
276}
277
278
279void crypto_global_deinit(void)
280{
281}