sha1-pbkdf2.c 2.3 KB

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