diff --git a/src/crypto.c b/src/crypto.c index b1b25c9d..a404aa7c 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -85,3 +86,43 @@ int crypto_psk_from_passphrase(const char *passphrase, return 0; } + +/* + * 802.11, Section 11.6.6.7: + * PTK = PRF-X(PMK, "Pairwise key expansion", Min(AA, SA) || Max(AA, SA) || + * Min(ANonce, SNonce) || Max(ANonce, SNonce)) + */ +bool crypto_derive_ptk(uint8_t *pmk, size_t pmk_len, const char *label, + uint8_t *addr1, uint8_t *addr2, + uint8_t *nonce1, uint8_t *nonce2, + uint8_t *out_ptk, size_t ptk_len) +{ + /* Nonce length is 32 */ + uint8_t data[ETH_ALEN * 2 + 64]; + size_t pos = 0; + + /* Address 1 is less than Address 2 */ + if (memcmp(addr1, addr2, ETH_ALEN) < 0) { + memcpy(data, addr1, ETH_ALEN); + memcpy(data + ETH_ALEN, addr2, ETH_ALEN); + } else { + memcpy(data, addr2, ETH_ALEN); + memcpy(data + ETH_ALEN, addr1, ETH_ALEN); + } + + pos += ETH_ALEN * 2; + + /* Nonce1 is less than Nonce2 */ + if (memcmp(nonce1, nonce2, 32) < 0) { + memcpy(data + pos, nonce1, 32); + memcpy(data + pos + 32, nonce2, 32); + } else { + memcpy(data + pos, nonce2, 32); + memcpy(data + pos + 32, nonce1, 32); + } + + pos += 64; + + return prf_sha1(pmk, pmk_len, label, strlen(label), + data, sizeof(data), out_ptk, ptk_len); +} diff --git a/src/crypto.h b/src/crypto.h index 99897c11..a78ff942 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -21,7 +21,13 @@ */ #include +#include int crypto_psk_from_passphrase(const char *passphrase, const unsigned char *ssid, size_t ssid_len, unsigned char *out_psk); + +bool crypto_derive_ptk(uint8_t *pmk, size_t pmk_len, const char *label, + uint8_t *addr1, uint8_t *addr2, + uint8_t *nonce1, uint8_t *nonce2, + uint8_t *out_ptk, size_t ptk_len);