$search
00001 /* 00002 * SHA1-based key derivation function (PBKDF2) for IEEE 802.11i 00003 * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "sha1.h" 00019 #include "md5.h" 00020 #include "crypto.h" 00021 00022 static int pbkdf2_sha1_f(const char *passphrase, const char *ssid, 00023 size_t ssid_len, int iterations, unsigned int count, 00024 u8 *digest) 00025 { 00026 unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN]; 00027 int i, j; 00028 unsigned char count_buf[4]; 00029 const u8 *addr[2]; 00030 size_t len[2]; 00031 size_t passphrase_len = os_strlen(passphrase); 00032 00033 addr[0] = (u8 *) ssid; 00034 len[0] = ssid_len; 00035 addr[1] = count_buf; 00036 len[1] = 4; 00037 00038 /* F(P, S, c, i) = U1 xor U2 xor ... Uc 00039 * U1 = PRF(P, S || i) 00040 * U2 = PRF(P, U1) 00041 * Uc = PRF(P, Uc-1) 00042 */ 00043 00044 count_buf[0] = (count >> 24) & 0xff; 00045 count_buf[1] = (count >> 16) & 0xff; 00046 count_buf[2] = (count >> 8) & 0xff; 00047 count_buf[3] = count & 0xff; 00048 if (hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, 00049 tmp)) 00050 return -1; 00051 os_memcpy(digest, tmp, SHA1_MAC_LEN); 00052 00053 for (i = 1; i < iterations; i++) { 00054 if (hmac_sha1((u8 *) passphrase, passphrase_len, tmp, 00055 SHA1_MAC_LEN, tmp2)) 00056 return -1; 00057 os_memcpy(tmp, tmp2, SHA1_MAC_LEN); 00058 for (j = 0; j < SHA1_MAC_LEN; j++) 00059 digest[j] ^= tmp2[j]; 00060 } 00061 00062 return 0; 00063 } 00064 00065 00080 int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, 00081 int iterations, u8 *buf, size_t buflen) 00082 { 00083 unsigned int count = 0; 00084 unsigned char *pos = buf; 00085 size_t left = buflen, plen; 00086 unsigned char digest[SHA1_MAC_LEN]; 00087 00088 while (left > 0) { 00089 count++; 00090 if (pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, 00091 count, digest)) 00092 return -1; 00093 plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left; 00094 os_memcpy(pos, digest, plen); 00095 pos += plen; 00096 left -= plen; 00097 } 00098 00099 return 0; 00100 }