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