Home | History | Annotate | Download | only in wpad
      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 (at) 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