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 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 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 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 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 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 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 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 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 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 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