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