xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.lib/wpad/wpa_enc.c (revision 11034:417289cdaf0e)
14126Szf162725 /*
2*11034SQuaker.Fang@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
34126Szf162725  * Use is subject to license terms.
44126Szf162725  */
54126Szf162725 
64126Szf162725 /*
74126Szf162725  * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
84126Szf162725  * Sun elects to license this software under the BSD license.
94126Szf162725  * See README for more details.
104126Szf162725  */
114126Szf162725 
124126Szf162725 #include <stdio.h>
134126Szf162725 #include <stdlib.h>
144126Szf162725 #include <string.h>
154126Szf162725 #include <strings.h>
164126Szf162725 #include <sys/types.h>
174126Szf162725 
184126Szf162725 #include <openssl/aes.h>
194126Szf162725 #include <openssl/hmac.h>
204126Szf162725 #include <openssl/rc4.h>
214126Szf162725 
224126Szf162725 #include "wpa_enc.h"
234126Szf162725 
244126Szf162725 /*
254126Szf162725  * @kek: key encryption key (KEK)
264126Szf162725  * @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
274126Szf162725  * @plain: plaintext key to be wrapped, n * 64 bit
284126Szf162725  * @cipher: wrapped key, (n + 1) * 64 bit
294126Szf162725  */
304126Szf162725 void
aes_wrap(uint8_t * kek,int n,uint8_t * plain,uint8_t * cipher)314126Szf162725 aes_wrap(uint8_t *kek, int n, uint8_t *plain, uint8_t *cipher)
324126Szf162725 {
334126Szf162725 	uint8_t *a, *r, b[16];
344126Szf162725 	int i, j;
354126Szf162725 	AES_KEY key;
364126Szf162725 
374126Szf162725 	a = cipher;
384126Szf162725 	r = cipher + 8;
394126Szf162725 
404126Szf162725 	/* 1) Initialize variables. */
414126Szf162725 	(void) memset(a, 0xa6, 8);
424126Szf162725 	(void) memcpy(r, plain, 8 * n);
434126Szf162725 
44*11034SQuaker.Fang@Sun.COM 	(void) AES_set_encrypt_key(kek, 128, &key);
454126Szf162725 
464126Szf162725 	/*
474126Szf162725 	 * 2) Calculate intermediate values.
484126Szf162725 	 * For j = 0 to 5
494126Szf162725 	 * 	For i=1 to n
504126Szf162725 	 * 		B = AES(K, A | R[i])
514126Szf162725 	 * 		A = MSB(64, B) ^ t where t = (n*j)+i
524126Szf162725 	 * 		R[i] = LSB(64, B)
534126Szf162725 	 */
544126Szf162725 	for (j = 0; j <= 5; j++) {
554126Szf162725 		r = cipher + 8;
564126Szf162725 		for (i = 1; i <= n; i++) {
574126Szf162725 			(void) memcpy(b, a, 8);
584126Szf162725 			(void) memcpy(b + 8, r, 8);
594126Szf162725 			AES_encrypt(b, b, &key);
604126Szf162725 			(void) memcpy(a, b, 8);
614126Szf162725 			a[7] ^= n * j + i;
624126Szf162725 			(void) memcpy(r, b + 8, 8);
634126Szf162725 			r += 8;
644126Szf162725 		}
654126Szf162725 	}
664126Szf162725 
674126Szf162725 	/*
684126Szf162725 	 * 3) Output the results.
694126Szf162725 	 *
704126Szf162725 	 * These are already in @cipher due to the location of temporary
714126Szf162725 	 * variables.
724126Szf162725 	 */
734126Szf162725 }
744126Szf162725 
754126Szf162725 /*
764126Szf162725  * @kek: key encryption key (KEK)
774126Szf162725  * @n: length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
784126Szf162725  * @cipher: wrapped key to be unwrapped, (n + 1) * 64 bit
794126Szf162725  * @plain: plaintext key, n * 64 bit
804126Szf162725  */
814126Szf162725 int
aes_unwrap(uint8_t * kek,int n,uint8_t * cipher,uint8_t * plain)824126Szf162725 aes_unwrap(uint8_t *kek, int n, uint8_t *cipher, uint8_t *plain)
834126Szf162725 {
844126Szf162725 	uint8_t a[8], *r, b[16];
854126Szf162725 	int i, j;
864126Szf162725 	AES_KEY key;
874126Szf162725 
884126Szf162725 	/* 1) Initialize variables. */
894126Szf162725 	(void) memcpy(a, cipher, 8);
904126Szf162725 	r = plain;
914126Szf162725 	(void) memcpy(r, cipher + 8, 8 * n);
924126Szf162725 
93*11034SQuaker.Fang@Sun.COM 	(void) AES_set_decrypt_key(kek, 128, &key);
944126Szf162725 
954126Szf162725 	/*
964126Szf162725 	 * 2) Compute intermediate values.
974126Szf162725 	 * For j = 5 to 0
984126Szf162725 	 * 	For i = n to 1
994126Szf162725 	 * 		B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
1004126Szf162725 	 * 		A = MSB(64, B)
1014126Szf162725 	 * 		R[i] = LSB(64, B)
1024126Szf162725 	 */
1034126Szf162725 	for (j = 5; j >= 0; j--) {
1044126Szf162725 		r = plain + (n - 1) * 8;
1054126Szf162725 		for (i = n; i >= 1; i--) {
1064126Szf162725 			(void) memcpy(b, a, 8);
1074126Szf162725 			b[7] ^= n * j + i;
1084126Szf162725 
1094126Szf162725 			(void) memcpy(b + 8, r, 8);
1104126Szf162725 			AES_decrypt(b, b, &key);
1114126Szf162725 			(void) memcpy(a, b, 8);
1124126Szf162725 			(void) memcpy(r, b + 8, 8);
1134126Szf162725 			r -= 8;
1144126Szf162725 		}
1154126Szf162725 	}
1164126Szf162725 
1174126Szf162725 	/*
1184126Szf162725 	 * 3) Output results.
1194126Szf162725 	 *
1204126Szf162725 	 * These are already in @plain due to the location of temporary
1214126Szf162725 	 * variables. Just verify that the IV matches with the expected value.
1224126Szf162725 	 */
1234126Szf162725 	for (i = 0; i < 8; i++) {
1244126Szf162725 		if (a[i] != 0xa6) {
1254126Szf162725 			return (-1);
1264126Szf162725 		}
1274126Szf162725 	}
1284126Szf162725 
1294126Szf162725 	return (0);
1304126Szf162725 }
1314126Szf162725 
1324126Szf162725 /* RFC 2104 */
1334126Szf162725 void
hmac_sha1(unsigned char * key,unsigned int key_len,unsigned char * data,unsigned int data_len,unsigned char * mac)1344126Szf162725 hmac_sha1(unsigned char *key, unsigned int key_len,
1354126Szf162725     unsigned char *data, unsigned int data_len, unsigned char *mac)
1364126Szf162725 {
1374126Szf162725 	unsigned int mac_len = 0;
138*11034SQuaker.Fang@Sun.COM 	(void) HMAC(EVP_sha1(), key, key_len, data, data_len, mac, &mac_len);
1394126Szf162725 }
1404126Szf162725 
1414126Szf162725 
1424126Szf162725 void
hmac_sha1_vector(unsigned char * key,unsigned int key_len,size_t num_elem,unsigned char * addr[],unsigned int * len,unsigned char * mac)1434126Szf162725 hmac_sha1_vector(unsigned char *key, unsigned int key_len, size_t num_elem,
1444126Szf162725     unsigned char *addr[], unsigned int *len, unsigned char *mac)
1454126Szf162725 {
1464126Szf162725 	unsigned char *buf, *ptr;
1474126Szf162725 	int i, buf_len;
1484126Szf162725 
1494126Szf162725 	buf_len = 0;
1504126Szf162725 	for (i = 0; i < num_elem; i ++)
1514126Szf162725 		buf_len += len[i];
1524126Szf162725 
1534126Szf162725 	buf = malloc(buf_len);
1544126Szf162725 	ptr = buf;
1554126Szf162725 
1564126Szf162725 	for (i = 0; i < num_elem; i ++) {
1574126Szf162725 		(void) memcpy(ptr, addr[i], len[i]);
1584126Szf162725 		ptr += len[i];
1594126Szf162725 	}
1604126Szf162725 
1614126Szf162725 	hmac_sha1(key, key_len, buf, buf_len, mac);
1624126Szf162725 
1634126Szf162725 	free(buf);
1644126Szf162725 }
1654126Szf162725 
1664126Szf162725 
1674126Szf162725 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)1684126Szf162725 sha1_prf(unsigned char *key, unsigned int key_len,
1694126Szf162725     char *label, unsigned char *data, unsigned int data_len,
1704126Szf162725     unsigned char *buf, size_t buf_len)
1714126Szf162725 {
1724126Szf162725 	uint8_t zero = 0, counter = 0;
1734126Szf162725 	size_t pos, plen;
1744126Szf162725 	uint8_t hash[SHA1_MAC_LEN];
1754126Szf162725 	size_t label_len = strlen(label);
1764126Szf162725 
1774126Szf162725 	unsigned char *addr[4];
1784126Szf162725 	unsigned int len[4];
1794126Szf162725 
1804126Szf162725 	addr[0] = (uint8_t *)label;
1814126Szf162725 	len[0] = label_len;
1824126Szf162725 	addr[1] = &zero;
1834126Szf162725 	len[1] = 1;
1844126Szf162725 	addr[2] = data;
1854126Szf162725 	len[2] = data_len;
1864126Szf162725 	addr[3] = &counter;
1874126Szf162725 	len[3] = 1;
1884126Szf162725 
1894126Szf162725 	pos = 0;
1904126Szf162725 	while (pos < buf_len) {
1914126Szf162725 		plen = buf_len - pos;
1924126Szf162725 		if (plen >= SHA1_MAC_LEN) {
1934126Szf162725 			hmac_sha1_vector(key, key_len, 4, addr, len, &buf[pos]);
1944126Szf162725 			pos += SHA1_MAC_LEN;
1954126Szf162725 		} else {
1964126Szf162725 			hmac_sha1_vector(key, key_len, 4, addr, len, hash);
1974126Szf162725 			(void) memcpy(&buf[pos], hash, plen);
1984126Szf162725 			break;
1994126Szf162725 		}
2004126Szf162725 		counter++;
2014126Szf162725 	}
2024126Szf162725 }
2034126Szf162725 
2044126Szf162725 void
pbkdf2_sha1(char * passphrase,char * ssid,size_t ssid_len,int iterations,unsigned char * buf,size_t buflen)2054126Szf162725 pbkdf2_sha1(char *passphrase, char *ssid, size_t ssid_len, int iterations,
2064126Szf162725     unsigned char *buf, size_t buflen)
2074126Szf162725 {
208*11034SQuaker.Fang@Sun.COM 	(void) PKCS5_PBKDF2_HMAC_SHA1(passphrase, -1, (unsigned char *)ssid,
209*11034SQuaker.Fang@Sun.COM 	    ssid_len, iterations, buflen, buf);
2104126Szf162725 }
2114126Szf162725 
2124126Szf162725 void
rc4_skip(uint8_t * key,size_t keylen,size_t skip,uint8_t * data,size_t data_len)2134126Szf162725 rc4_skip(uint8_t *key, size_t keylen, size_t skip,
2144126Szf162725     uint8_t *data, size_t data_len)
2154126Szf162725 {
2164126Szf162725 	uint8_t *buf;
2174126Szf162725 	size_t buf_len;
2184126Szf162725 
2194126Szf162725 	buf_len = skip + data_len;
2204126Szf162725 	buf = malloc(buf_len);
2214126Szf162725 
2224126Szf162725 	bzero(buf, buf_len);
2234126Szf162725 	bcopy(data, buf + skip, data_len);
2244126Szf162725 
2254126Szf162725 	rc4(buf, buf_len, key, keylen);
2264126Szf162725 
2274126Szf162725 	bcopy(buf + skip, data, data_len);
2284126Szf162725 	free(buf);
2294126Szf162725 }
2304126Szf162725 
2314126Szf162725 void
rc4(uint8_t * buf,size_t len,uint8_t * key,size_t key_len)2324126Szf162725 rc4(uint8_t *buf, size_t len, uint8_t *key, size_t key_len)
2334126Szf162725 {
2344126Szf162725 	RC4_KEY k;
2354126Szf162725 
2364126Szf162725 	RC4_set_key(&k, key_len, key);
2374126Szf162725 	RC4(&k, len, buf, buf);
2384126Szf162725 }
2394126Szf162725 
2404126Szf162725 void
hmac_md5_vector(uint8_t * key,size_t key_len,size_t num_elem,uint8_t * addr[],size_t * len,uint8_t * mac)2414126Szf162725 hmac_md5_vector(uint8_t *key, size_t key_len, size_t num_elem,
2424126Szf162725     uint8_t *addr[], size_t *len, uint8_t *mac)
2434126Szf162725 {
2444126Szf162725 	unsigned char *buf, *ptr;
2454126Szf162725 	int i, buf_len;
2464126Szf162725 
2474126Szf162725 	buf_len = 0;
2484126Szf162725 	for (i = 0; i < num_elem; i ++)
2494126Szf162725 		buf_len += len[i];
2504126Szf162725 
2514126Szf162725 	buf = malloc(buf_len);
2524126Szf162725 	ptr = buf;
2534126Szf162725 
2544126Szf162725 	for (i = 0; i < num_elem; i ++) {
2554126Szf162725 		(void) memcpy(ptr, addr[i], len[i]);
2564126Szf162725 		ptr += len[i];
2574126Szf162725 	}
2584126Szf162725 
2594126Szf162725 	hmac_md5(key, key_len, buf, buf_len, mac);
2604126Szf162725 	free(buf);
2614126Szf162725 }
2624126Szf162725 
2634126Szf162725 /* RFC 2104 */
2644126Szf162725 void
hmac_md5(uint8_t * key,size_t key_len,uint8_t * data,size_t data_len,uint8_t * mac)2654126Szf162725 hmac_md5(uint8_t *key, size_t key_len, uint8_t *data,
2664126Szf162725     size_t data_len, uint8_t *mac)
2674126Szf162725 {
2684126Szf162725 	unsigned int mac_len = 0;
269*11034SQuaker.Fang@Sun.COM 	(void) HMAC(EVP_md5(), key, key_len, data, data_len, mac, &mac_len);
2704126Szf162725 }
271