diff --git a/Makefile.am b/Makefile.am index 63786894..1cbaf988 100644 --- a/Makefile.am +++ b/Makefile.am @@ -140,7 +140,7 @@ unit_test_hmac_sha256_SOURCES = unit/test-hmac-sha256.c \ unit_test_hmac_sha256_LDADD = ell/libell-internal.la unit_test_pbkdf2_sha1_SOURCES = unit/test-pbkdf2-sha1.c \ - src/sha1.h src/sha1.c + src/crypto.h src/crypto.c unit_test_pbkdf2_sha1_LDADD = ell/libell-internal.la unit_test_prf_sha1_SOURCES = unit/test-prf-sha1.c \ diff --git a/src/crypto.c b/src/crypto.c index 5291e7a1..7efb5ae5 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -188,6 +188,66 @@ int crypto_cipher_tk_bits(enum crypto_cipher cipher) return crypto_cipher_key_len(cipher) * 8; } +#define SHA1_MAC_LEN 20 + +static void F(struct l_checksum *checksum, + const char *salt, size_t salt_len, + unsigned int iterations, unsigned int count, + unsigned char *digest) +{ + unsigned char tmp[SHA1_MAC_LEN]; + unsigned char buf[36]; + unsigned int i, j; + + memcpy(buf, salt, salt_len); + buf[salt_len + 0] = (count >> 24) & 0xff; + buf[salt_len + 1] = (count >> 16) & 0xff; + buf[salt_len + 2] = (count >> 8) & 0xff; + buf[salt_len + 3] = count & 0xff; + + l_checksum_update(checksum, buf, salt_len + 4); + l_checksum_get_digest(checksum, tmp, SHA1_MAC_LEN); + memcpy(digest, tmp, SHA1_MAC_LEN); + + for (i = 1; i < iterations; i++) { + l_checksum_update(checksum, tmp, SHA1_MAC_LEN); + l_checksum_get_digest(checksum, tmp, SHA1_MAC_LEN); + + for (j = 0; j < SHA1_MAC_LEN; j++) + digest[j] ^= tmp[j]; + } +} + +bool pbkdf2_sha1(const void *password, size_t password_len, + const void *salt, size_t salt_len, + unsigned int iterations, void *output, size_t size) +{ + struct l_checksum *checksum; + unsigned char *ptr = output; + unsigned char digest[SHA1_MAC_LEN]; + unsigned int i; + + checksum = l_checksum_new_hmac(L_CHECKSUM_SHA1, password, password_len); + if (!checksum) + return false; + + for (i = 1; size > 0; i++) { + size_t len; + + F(checksum, salt, salt_len, iterations, i, digest); + + len = size > SHA1_MAC_LEN ? SHA1_MAC_LEN : size; + memcpy(ptr, digest, len); + + ptr += len; + size -= len; + } + + l_checksum_free(checksum); + + return true; +} + int crypto_psk_from_passphrase(const char *passphrase, const unsigned char *ssid, size_t ssid_len, unsigned char *out_psk) diff --git a/src/crypto.h b/src/crypto.h index 8110203d..7c79f950 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -54,6 +54,10 @@ bool arc4_skip(const uint8_t *key, size_t key_len, size_t skip, int crypto_cipher_key_len(enum crypto_cipher cipher); int crypto_cipher_tk_bits(enum crypto_cipher cipher); +bool pbkdf2_sha1(const void *password, size_t password_len, + const void *salt, size_t salt_len, + unsigned int iterations, void *output, size_t size); + int crypto_psk_from_passphrase(const char *passphrase, const unsigned char *ssid, size_t ssid_len, unsigned char *out_psk); diff --git a/src/sha1.c b/src/sha1.c index f04c10b8..a807af5f 100644 --- a/src/sha1.c +++ b/src/sha1.c @@ -27,112 +27,3 @@ #include #include -#include "src/sha1.h" - -#define SHA1_MAC_LEN 20 - -static void __hmac_sha1(struct l_checksum *checksum, - const void *key, size_t key_len, - const void *data, size_t data_len, - void *output, size_t size) -{ - unsigned char ipad[64]; - unsigned char opad[64]; - unsigned char digest[SHA1_MAC_LEN]; - int i; - - /* if key is longer than 64 bytes reset it to key=SHA1(key) */ - if (key_len > 64) { - l_checksum_update(checksum, key, key_len); - l_checksum_get_digest(checksum, digest, SHA1_MAC_LEN); - - key = digest; - key_len = SHA1_MAC_LEN; - } - - /* start out by storing key in pads */ - memset(ipad, 0, sizeof(ipad)); - memset(opad, 0, sizeof(opad)); - memcpy(ipad, key, key_len); - memcpy(opad, key, key_len); - - /* XOR key with ipad and opad values */ - for (i = 0; i < 64; i++) { - ipad[i] ^= 0x36; - opad[i] ^= 0x5c; - } - - /* perform inner SHA1 */ - l_checksum_update(checksum, ipad, sizeof(ipad)); - l_checksum_update(checksum, data, data_len); - l_checksum_get_digest(checksum, digest, SHA1_MAC_LEN); - - /* perform outer SHA1 */ - l_checksum_update(checksum, opad, sizeof(opad)); - l_checksum_update(checksum, digest, SHA1_MAC_LEN); - l_checksum_get_digest(checksum, output, - size > SHA1_MAC_LEN ? SHA1_MAC_LEN : size); -} - -static void F(struct l_checksum *checksum, - const char *password, size_t password_len, - const char *salt, size_t salt_len, - unsigned int iterations, unsigned int count, - unsigned char *digest) -{ - unsigned char tmp1[SHA1_MAC_LEN]; - unsigned char tmp2[SHA1_MAC_LEN]; - unsigned char buf[36]; - unsigned int i, j; - - memcpy(buf, salt, salt_len); - buf[salt_len + 0] = (count >> 24) & 0xff; - buf[salt_len + 1] = (count >> 16) & 0xff; - buf[salt_len + 2] = (count >> 8) & 0xff; - buf[salt_len + 3] = count & 0xff; - - __hmac_sha1(checksum, password, password_len, - buf, salt_len + 4, tmp1, SHA1_MAC_LEN); - memcpy(digest, tmp1, SHA1_MAC_LEN); - - for (i = 1; i < iterations; i++) { - __hmac_sha1(checksum, password, password_len, - tmp1, SHA1_MAC_LEN, tmp2, SHA1_MAC_LEN); - memcpy(tmp1, tmp2, SHA1_MAC_LEN); - - for (j = 0; j < SHA1_MAC_LEN; j++) - digest[j] ^= tmp2[j]; - } -} - -bool pbkdf2_sha1(const void *password, size_t password_len, - const void *salt, size_t salt_len, - unsigned int iterations, void *output, size_t size) -{ - struct l_checksum *checksum; - unsigned char *ptr = output; - unsigned char digest[SHA1_MAC_LEN]; - unsigned int i; - - checksum = l_checksum_new(L_CHECKSUM_SHA1); - if (!checksum) - return false; - - for (i = 1; size > 0; i++) { - size_t len; - - F(checksum, password, password_len, salt, salt_len, - iterations, i, digest); - - len = size > SHA1_MAC_LEN ? SHA1_MAC_LEN : size; - memcpy(ptr, digest, len); - - ptr += len; - size -= len; - } - - l_checksum_free(checksum); - - return true; -} - diff --git a/src/sha1.h b/src/sha1.h index 9da3b6ba..8b608cbd 100644 --- a/src/sha1.h +++ b/src/sha1.h @@ -22,6 +22,3 @@ #include -bool pbkdf2_sha1(const void *password, size_t password_len, - const void *salt, size_t salt_len, - unsigned int iterations, void *output, size_t size);