1 /*
2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /*
7 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
8 * Sun elects to license this software under the BSD license.
9 * See README for more details.
10 */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <strings.h>
16 #include <sys/types.h>
17
18 #include <openssl/aes.h>
19 #include <openssl/hmac.h>
20 #include <openssl/rc4.h>
21
22 #include "wpa_enc.h"
23
24 /*
25 * @kek: key encryption key (KEK)
26 * @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
27 * @plain: plaintext key to be wrapped, n * 64 bit
28 * @cipher: wrapped key, (n + 1) * 64 bit
29 */
30 void
aes_wrap(uint8_t * kek,int n,uint8_t * plain,uint8_t * cipher)31 aes_wrap(uint8_t *kek, int n, uint8_t *plain, uint8_t *cipher)
32 {
33 uint8_t *a, *r, b[16];
34 int i, j;
35 AES_KEY key;
36
37 a = cipher;
38 r = cipher + 8;
39
40 /* 1) Initialize variables. */
41 (void) memset(a, 0xa6, 8);
42 (void) memcpy(r, plain, 8 * n);
43
44 (void) AES_set_encrypt_key(kek, 128, &key);
45
46 /*
47 * 2) Calculate intermediate values.
48 * For j = 0 to 5
49 * For i=1 to n
50 * B = AES(K, A | R[i])
51 * A = MSB(64, B) ^ t where t = (n*j)+i
52 * R[i] = LSB(64, B)
53 */
54 for (j = 0; j <= 5; j++) {
55 r = cipher + 8;
56 for (i = 1; i <= n; i++) {
57 (void) memcpy(b, a, 8);
58 (void) memcpy(b + 8, r, 8);
59 AES_encrypt(b, b, &key);
60 (void) memcpy(a, b, 8);
61 a[7] ^= n * j + i;
62 (void) memcpy(r, b + 8, 8);
63 r += 8;
64 }
65 }
66
67 /*
68 * 3) Output the results.
69 *
70 * These are already in @cipher due to the location of temporary
71 * variables.
72 */
73 }
74
75 /*
76 * @kek: key encryption key (KEK)
77 * @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
78 * @cipher: wrapped key to be unwrapped, (n + 1) * 64 bit
79 * @plain: plaintext key, n * 64 bit
80 */
81 int
aes_unwrap(uint8_t * kek,int n,uint8_t * cipher,uint8_t * plain)82 aes_unwrap(uint8_t *kek, int n, uint8_t *cipher, uint8_t *plain)
83 {
84 uint8_t a[8], *r, b[16];
85 int i, j;
86 AES_KEY key;
87
88 /* 1) Initialize variables. */
89 (void) memcpy(a, cipher, 8);
90 r = plain;
91 (void) memcpy(r, cipher + 8, 8 * n);
92
93 (void) AES_set_decrypt_key(kek, 128, &key);
94
95 /*
96 * 2) Compute intermediate values.
97 * For j = 5 to 0
98 * For i = n to 1
99 * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
100 * A = MSB(64, B)
101 * R[i] = LSB(64, B)
102 */
103 for (j = 5; j >= 0; j--) {
104 r = plain + (n - 1) * 8;
105 for (i = n; i >= 1; i--) {
106 (void) memcpy(b, a, 8);
107 b[7] ^= n * j + i;
108
109 (void) memcpy(b + 8, r, 8);
110 AES_decrypt(b, b, &key);
111 (void) memcpy(a, b, 8);
112 (void) memcpy(r, b + 8, 8);
113 r -= 8;
114 }
115 }
116
117 /*
118 * 3) Output results.
119 *
120 * These are already in @plain due to the location of temporary
121 * variables. Just verify that the IV matches with the expected value.
122 */
123 for (i = 0; i < 8; i++) {
124 if (a[i] != 0xa6) {
125 return (-1);
126 }
127 }
128
129 return (0);
130 }
131
132 /* RFC 2104 */
133 void
hmac_sha1(unsigned char * key,unsigned int key_len,unsigned char * data,unsigned int data_len,unsigned char * mac)134 hmac_sha1(unsigned char *key, unsigned int key_len,
135 unsigned char *data, unsigned int data_len, unsigned char *mac)
136 {
137 unsigned int mac_len = 0;
138 (void) HMAC(EVP_sha1(), key, key_len, data, data_len, mac, &mac_len);
139 }
140
141
142 void
hmac_sha1_vector(unsigned char * key,unsigned int key_len,size_t num_elem,unsigned char * addr[],unsigned int * len,unsigned char * mac)143 hmac_sha1_vector(unsigned char *key, unsigned int key_len, size_t num_elem,
144 unsigned char *addr[], unsigned int *len, unsigned char *mac)
145 {
146 unsigned char *buf, *ptr;
147 int i, buf_len;
148
149 buf_len = 0;
150 for (i = 0; i < num_elem; i ++)
151 buf_len += len[i];
152
153 buf = malloc(buf_len);
154 ptr = buf;
155
156 for (i = 0; i < num_elem; i ++) {
157 (void) memcpy(ptr, addr[i], len[i]);
158 ptr += len[i];
159 }
160
161 hmac_sha1(key, key_len, buf, buf_len, mac);
162
163 free(buf);
164 }
165
166
167 void
sha1_prf(unsigned char * key,unsigned int key_len,char * label,unsigned char * data,unsigned int data_len,unsigned char * buf,size_t buf_len)168 sha1_prf(unsigned char *key, unsigned int key_len,
169 char *label, unsigned char *data, unsigned int data_len,
170 unsigned char *buf, size_t buf_len)
171 {
172 uint8_t zero = 0, counter = 0;
173 size_t pos, plen;
174 uint8_t hash[SHA1_MAC_LEN];
175 size_t label_len = strlen(label);
176
177 unsigned char *addr[4];
178 unsigned int len[4];
179
180 addr[0] = (uint8_t *)label;
181 len[0] = label_len;
182 addr[1] = &zero;
183 len[1] = 1;
184 addr[2] = data;
185 len[2] = data_len;
186 addr[3] = &counter;
187 len[3] = 1;
188
189 pos = 0;
190 while (pos < buf_len) {
191 plen = buf_len - pos;
192 if (plen >= SHA1_MAC_LEN) {
193 hmac_sha1_vector(key, key_len, 4, addr, len, &buf[pos]);
194 pos += SHA1_MAC_LEN;
195 } else {
196 hmac_sha1_vector(key, key_len, 4, addr, len, hash);
197 (void) memcpy(&buf[pos], hash, plen);
198 break;
199 }
200 counter++;
201 }
202 }
203
204 void
pbkdf2_sha1(char * passphrase,char * ssid,size_t ssid_len,int iterations,unsigned char * buf,size_t buflen)205 pbkdf2_sha1(char *passphrase, char *ssid, size_t ssid_len, int iterations,
206 unsigned char *buf, size_t buflen)
207 {
208 (void) PKCS5_PBKDF2_HMAC_SHA1(passphrase, -1, (unsigned char *)ssid,
209 ssid_len, iterations, buflen, buf);
210 }
211
212 void
rc4_skip(uint8_t * key,size_t keylen,size_t skip,uint8_t * data,size_t data_len)213 rc4_skip(uint8_t *key, size_t keylen, size_t skip,
214 uint8_t *data, size_t data_len)
215 {
216 uint8_t *buf;
217 size_t buf_len;
218
219 buf_len = skip + data_len;
220 buf = malloc(buf_len);
221
222 bzero(buf, buf_len);
223 bcopy(data, buf + skip, data_len);
224
225 rc4(buf, buf_len, key, keylen);
226
227 bcopy(buf + skip, data, data_len);
228 free(buf);
229 }
230
231 void
rc4(uint8_t * buf,size_t len,uint8_t * key,size_t key_len)232 rc4(uint8_t *buf, size_t len, uint8_t *key, size_t key_len)
233 {
234 RC4_KEY k;
235
236 RC4_set_key(&k, key_len, key);
237 RC4(&k, len, buf, buf);
238 }
239
240 void
hmac_md5_vector(uint8_t * key,size_t key_len,size_t num_elem,uint8_t * addr[],size_t * len,uint8_t * mac)241 hmac_md5_vector(uint8_t *key, size_t key_len, size_t num_elem,
242 uint8_t *addr[], size_t *len, uint8_t *mac)
243 {
244 unsigned char *buf, *ptr;
245 int i, buf_len;
246
247 buf_len = 0;
248 for (i = 0; i < num_elem; i ++)
249 buf_len += len[i];
250
251 buf = malloc(buf_len);
252 ptr = buf;
253
254 for (i = 0; i < num_elem; i ++) {
255 (void) memcpy(ptr, addr[i], len[i]);
256 ptr += len[i];
257 }
258
259 hmac_md5(key, key_len, buf, buf_len, mac);
260 free(buf);
261 }
262
263 /* RFC 2104 */
264 void
hmac_md5(uint8_t * key,size_t key_len,uint8_t * data,size_t data_len,uint8_t * mac)265 hmac_md5(uint8_t *key, size_t key_len, uint8_t *data,
266 size_t data_len, uint8_t *mac)
267 {
268 unsigned int mac_len = 0;
269 (void) HMAC(EVP_md5(), key, key_len, data, data_len, mac, &mac_len);
270 }
271