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