1 /* 2 * SHA1-based key derivation function (PBKDF2) for IEEE 802.11i 3 * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 #include "sha1.h" 13 14 static int pbkdf2_sha1_f(const char *passphrase, const u8 *ssid, 15 size_t ssid_len, int iterations, unsigned int count, 16 u8 *digest) 17 { 18 unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN]; 19 int i, j; 20 unsigned char count_buf[4]; 21 const u8 *addr[2]; 22 size_t len[2]; 23 size_t passphrase_len = os_strlen(passphrase); 24 25 addr[0] = ssid; 26 len[0] = ssid_len; 27 addr[1] = count_buf; 28 len[1] = 4; 29 30 /* F(P, S, c, i) = U1 xor U2 xor ... Uc 31 * U1 = PRF(P, S || i) 32 * U2 = PRF(P, U1) 33 * Uc = PRF(P, Uc-1) 34 */ 35 36 count_buf[0] = (count >> 24) & 0xff; 37 count_buf[1] = (count >> 16) & 0xff; 38 count_buf[2] = (count >> 8) & 0xff; 39 count_buf[3] = count & 0xff; 40 if (hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, 41 tmp)) 42 return -1; 43 os_memcpy(digest, tmp, SHA1_MAC_LEN); 44 45 for (i = 1; i < iterations; i++) { 46 if (hmac_sha1((u8 *) passphrase, passphrase_len, tmp, 47 SHA1_MAC_LEN, tmp2)) 48 return -1; 49 os_memcpy(tmp, tmp2, SHA1_MAC_LEN); 50 for (j = 0; j < SHA1_MAC_LEN; j++) 51 digest[j] ^= tmp2[j]; 52 } 53 forced_memzero(tmp, SHA1_MAC_LEN); 54 forced_memzero(tmp2, SHA1_MAC_LEN); 55 56 return 0; 57 } 58 59 60 /** 61 * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i 62 * @passphrase: ASCII passphrase 63 * @ssid: SSID 64 * @ssid_len: SSID length in bytes 65 * @iterations: Number of iterations to run 66 * @buf: Buffer for the generated key 67 * @buflen: Length of the buffer in bytes 68 * Returns: 0 on success, -1 of failure 69 * 70 * This function is used to derive PSK for WPA-PSK. For this protocol, 71 * iterations is set to 4096 and buflen to 32. This function is described in 72 * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0. 73 */ 74 int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, 75 int iterations, u8 *buf, size_t buflen) 76 { 77 unsigned int count = 0; 78 unsigned char *pos = buf; 79 size_t left = buflen, plen; 80 unsigned char digest[SHA1_MAC_LEN]; 81 82 while (left > 0) { 83 count++; 84 if (pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, 85 count, digest)) 86 return -1; 87 plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left; 88 os_memcpy(pos, digest, plen); 89 pos += plen; 90 left -= plen; 91 } 92 forced_memzero(digest, SHA1_MAC_LEN); 93 94 return 0; 95 } 96