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