remove @EAP_LDFLAGS@, no longer exists
[mech_eap.orig] / libeap / src / crypto / crypto_internal.c
1 /*
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
22 struct 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
33 struct 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
99 void 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
117 int 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
197 int crypto_global_init(void)
198 {
199         return 0;
200 }
201
202
203 void crypto_global_deinit(void)
204 {
205 }