1 /* 2 * SHA1-based key derivation function (PBKDF2) for IEEE 802.11i 3 * Copyright (c) 2003-2005, Jouni Malinen <j (at) 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 char *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] = (u8 *) 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 54 return 0; 55 } 56 57 58 /** 59 * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i 60 * @passphrase: ASCII passphrase 61 * @ssid: SSID 62 * @ssid_len: SSID length in bytes 63 * @iterations: Number of iterations to run 64 * @buf: Buffer for the generated key 65 * @buflen: Length of the buffer in bytes 66 * Returns: 0 on success, -1 of failure 67 * 68 * This function is used to derive PSK for WPA-PSK. For this protocol, 69 * iterations is set to 4096 and buflen to 32. This function is described in 70 * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0. 71 */ 72 int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, 73 int iterations, u8 *buf, size_t buflen) 74 { 75 unsigned int count = 0; 76 unsigned char *pos = buf; 77 size_t left = buflen, plen; 78 unsigned char digest[SHA1_MAC_LEN]; 79 80 while (left > 0) { 81 count++; 82 if (pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, 83 count, digest)) 84 return -1; 85 plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left; 86 os_memcpy(pos, digest, plen); 87 pos += plen; 88 left -= plen; 89 } 90 91 return 0; 92 } 93