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