blob: 8fdba65802750d2a374919f3bed0e62e93ced2a0 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * Crypto wrapper for internal crypto implementation
3 * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
4 *
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"
19#include "sha1_i.h"
20#include "md5_i.h"
21
22struct crypto_hash {
23 enum crypto_hash_alg alg;
24 union {
25 struct MD5Context md5;
26 struct SHA1Context sha1;
27 } u;
28 u8 key[64];
29 size_t key_len;
30};
31
32
33struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
34 size_t key_len)
35{
36 struct crypto_hash *ctx;
37 u8 k_pad[64];
38 u8 tk[20];
39 size_t i;
40
41 ctx = os_zalloc(sizeof(*ctx));
42 if (ctx == NULL)
43 return NULL;
44
45 ctx->alg = alg;
46
47 switch (alg) {
48 case CRYPTO_HASH_ALG_MD5:
49 MD5Init(&ctx->u.md5);
50 break;
51 case CRYPTO_HASH_ALG_SHA1:
52 SHA1Init(&ctx->u.sha1);
53 break;
54 case CRYPTO_HASH_ALG_HMAC_MD5:
55 if (key_len > sizeof(k_pad)) {
56 MD5Init(&ctx->u.md5);
57 MD5Update(&ctx->u.md5, key, key_len);
58 MD5Final(tk, &ctx->u.md5);
59 key = tk;
60 key_len = 16;
61 }
62 os_memcpy(ctx->key, key, key_len);
63 ctx->key_len = key_len;
64
65 os_memcpy(k_pad, key, key_len);
66 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
67 for (i = 0; i < sizeof(k_pad); i++)
68 k_pad[i] ^= 0x36;
69 MD5Init(&ctx->u.md5);
70 MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
71 break;
72 case CRYPTO_HASH_ALG_HMAC_SHA1:
73 if (key_len > sizeof(k_pad)) {
74 SHA1Init(&ctx->u.sha1);
75 SHA1Update(&ctx->u.sha1, key, key_len);
76 SHA1Final(tk, &ctx->u.sha1);
77 key = tk;
78 key_len = 20;
79 }
80 os_memcpy(ctx->key, key, key_len);
81 ctx->key_len = key_len;
82
83 os_memcpy(k_pad, key, key_len);
84 os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
85 for (i = 0; i < sizeof(k_pad); i++)
86 k_pad[i] ^= 0x36;
87 SHA1Init(&ctx->u.sha1);
88 SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
89 break;
90 default:
91 os_free(ctx);
92 return NULL;
93 }
94
95 return ctx;
96}
97
98
99void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
100{
101 if (ctx == NULL)
102 return;
103
104 switch (ctx->alg) {
105 case CRYPTO_HASH_ALG_MD5:
106 case CRYPTO_HASH_ALG_HMAC_MD5:
107 MD5Update(&ctx->u.md5, data, len);
108 break;
109 case CRYPTO_HASH_ALG_SHA1:
110 case CRYPTO_HASH_ALG_HMAC_SHA1:
111 SHA1Update(&ctx->u.sha1, data, len);
112 break;
113 }
114}
115
116
117int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
118{
119 u8 k_pad[64];
120 size_t i;
121
122 if (ctx == NULL)
123 return -2;
124
125 if (mac == NULL || len == NULL) {
126 os_free(ctx);
127 return 0;
128 }
129
130 switch (ctx->alg) {
131 case CRYPTO_HASH_ALG_MD5:
132 if (*len < 16) {
133 *len = 16;
134 os_free(ctx);
135 return -1;
136 }
137 *len = 16;
138 MD5Final(mac, &ctx->u.md5);
139 break;
140 case CRYPTO_HASH_ALG_SHA1:
141 if (*len < 20) {
142 *len = 20;
143 os_free(ctx);
144 return -1;
145 }
146 *len = 20;
147 SHA1Final(mac, &ctx->u.sha1);
148 break;
149 case CRYPTO_HASH_ALG_HMAC_MD5:
150 if (*len < 16) {
151 *len = 16;
152 os_free(ctx);
153 return -1;
154 }
155 *len = 16;
156
157 MD5Final(mac, &ctx->u.md5);
158
159 os_memcpy(k_pad, ctx->key, ctx->key_len);
160 os_memset(k_pad + ctx->key_len, 0,
161 sizeof(k_pad) - ctx->key_len);
162 for (i = 0; i < sizeof(k_pad); i++)
163 k_pad[i] ^= 0x5c;
164 MD5Init(&ctx->u.md5);
165 MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
166 MD5Update(&ctx->u.md5, mac, 16);
167 MD5Final(mac, &ctx->u.md5);
168 break;
169 case CRYPTO_HASH_ALG_HMAC_SHA1:
170 if (*len < 20) {
171 *len = 20;
172 os_free(ctx);
173 return -1;
174 }
175 *len = 20;
176
177 SHA1Final(mac, &ctx->u.sha1);
178
179 os_memcpy(k_pad, ctx->key, ctx->key_len);
180 os_memset(k_pad + ctx->key_len, 0,
181 sizeof(k_pad) - ctx->key_len);
182 for (i = 0; i < sizeof(k_pad); i++)
183 k_pad[i] ^= 0x5c;
184 SHA1Init(&ctx->u.sha1);
185 SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
186 SHA1Update(&ctx->u.sha1, mac, 20);
187 SHA1Final(mac, &ctx->u.sha1);
188 break;
189 }
190
191 os_free(ctx);
192
193 return 0;
194}
195
196
197int crypto_global_init(void)
198{
199 return 0;
200}
201
202
203void crypto_global_deinit(void)
204{
205}