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