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 */
30void
31aes_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 */
81int
82aes_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 */
133void
134hmac_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
142void
143hmac_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
167void
168sha1_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
204void
205pbkdf2_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
212void
213rc4_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
231void
232rc4(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
240void
241hmac_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 */
264void
265hmac_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