crypto/handshake/eapol: Allow other PTK lengths

The crypto_ptk was hard coded for 16 byte KCK/KEK. Depending on the
AKM these can be up to 32 bytes. This changes completely removes the
crypto_ptk struct and adds getters to the handshake object for the
kck and kek. Like before the PTK is derived into a continuous buffer,
and the kck/kek getters take care of returning the proper key offset
depending on AKM.

To allow for larger than 16 byte keys aes_unwrap needed to be
modified to take the kek length.
This commit is contained in:
James Prestwood 2019-01-17 12:25:30 -08:00 committed by Denis Kenzior
parent 3b801526f0
commit 6771a06463
6 changed files with 138 additions and 65 deletions

View File

@ -129,7 +129,7 @@ bool cmac_aes(const void *key, size_t key_len,
* *
* NOTE: Buffers @in and @out can overlap * NOTE: Buffers @in and @out can overlap
*/ */
bool aes_unwrap(const uint8_t *kek, const uint8_t *in, size_t len, bool aes_unwrap(const uint8_t *kek, size_t kek_len, const uint8_t *in, size_t len,
uint8_t *out) uint8_t *out)
{ {
uint64_t b[2]; uint64_t b[2];
@ -139,7 +139,7 @@ bool aes_unwrap(const uint8_t *kek, const uint8_t *in, size_t len,
struct l_cipher *cipher; struct l_cipher *cipher;
uint64_t t = n * 6; uint64_t t = n * 6;
cipher = l_cipher_new(L_CIPHER_AES, kek, 16); cipher = l_cipher_new(L_CIPHER_AES, kek, kek_len);
if (!cipher) if (!cipher)
return false; return false;
@ -552,7 +552,6 @@ static bool crypto_derive_ptk(const uint8_t *pmk, size_t pmk_len,
} }
pos += 64; pos += 64;
if (use_sha256) if (use_sha256)
return kdf_sha256(pmk, pmk_len, label, strlen(label), return kdf_sha256(pmk, pmk_len, label, strlen(label),
data, sizeof(data), out_ptk, ptk_len); data, sizeof(data), out_ptk, ptk_len);
@ -564,12 +563,12 @@ static bool crypto_derive_ptk(const uint8_t *pmk, size_t pmk_len,
bool crypto_derive_pairwise_ptk(const uint8_t *pmk, bool crypto_derive_pairwise_ptk(const uint8_t *pmk,
const uint8_t *addr1, const uint8_t *addr2, const uint8_t *addr1, const uint8_t *addr2,
const uint8_t *nonce1, const uint8_t *nonce2, const uint8_t *nonce1, const uint8_t *nonce2,
struct crypto_ptk *out_ptk, size_t ptk_len, uint8_t *out_ptk, size_t ptk_len,
bool use_sha256) bool use_sha256)
{ {
return crypto_derive_ptk(pmk, 32, "Pairwise key expansion", return crypto_derive_ptk(pmk, 32, "Pairwise key expansion",
addr1, addr2, nonce1, nonce2, addr1, addr2, nonce1, nonce2,
(uint8_t *) out_ptk, ptk_len, out_ptk, ptk_len,
use_sha256); use_sha256);
} }
@ -677,7 +676,7 @@ exit:
bool crypto_derive_ft_ptk(const uint8_t *pmk_r1, const uint8_t *pmk_r1_name, bool crypto_derive_ft_ptk(const uint8_t *pmk_r1, const uint8_t *pmk_r1_name,
const uint8_t *addr1, const uint8_t *addr2, const uint8_t *addr1, const uint8_t *addr2,
const uint8_t *nonce1, const uint8_t *nonce2, const uint8_t *nonce1, const uint8_t *nonce2,
struct crypto_ptk *out_ptk, size_t ptk_len, uint8_t *out_ptk, size_t ptk_len,
uint8_t *out_ptk_name) uint8_t *out_ptk_name)
{ {
uint8_t context[ETH_ALEN * 2 + 64]; uint8_t context[ETH_ALEN * 2 + 64];

View File

@ -54,12 +54,6 @@ enum crypto_akm {
#define CRYPTO_MIN_IGTK_LEN 16 #define CRYPTO_MIN_IGTK_LEN 16
#define CRYPTO_MAX_IGTK_LEN 32 #define CRYPTO_MAX_IGTK_LEN 32
struct crypto_ptk {
uint8_t kck[16];
uint8_t kek[16];
uint8_t tk[0];
} __attribute__ ((packed));
extern const unsigned char crypto_dh5_prime[]; extern const unsigned char crypto_dh5_prime[];
extern size_t crypto_dh5_prime_size; extern size_t crypto_dh5_prime_size;
extern const unsigned char crypto_dh5_generator[]; extern const unsigned char crypto_dh5_generator[];
@ -76,7 +70,7 @@ bool hmac_sha384(const void *key, size_t key_len,
bool cmac_aes(const void *key, size_t key_len, bool cmac_aes(const void *key, size_t key_len,
const void *data, size_t data_len, void *output, size_t size); const void *data, size_t data_len, void *output, size_t size);
bool aes_unwrap(const uint8_t *kek, const uint8_t *in, size_t len, bool aes_unwrap(const uint8_t *kek, size_t kek_len, const uint8_t *in, size_t len,
uint8_t *out); uint8_t *out);
bool aes_wrap(const uint8_t *kek, const uint8_t *in, size_t len, uint8_t *out); bool aes_wrap(const uint8_t *kek, const uint8_t *in, size_t len, uint8_t *out);
bool arc4_skip(const uint8_t *key, size_t key_len, size_t skip, bool arc4_skip(const uint8_t *key, size_t key_len, size_t skip,
@ -104,7 +98,7 @@ bool hkdf_expand_sha256(const uint8_t *key, size_t key_len, const char *info,
bool crypto_derive_pairwise_ptk(const uint8_t *pmk, bool crypto_derive_pairwise_ptk(const uint8_t *pmk,
const uint8_t *addr1, const uint8_t *addr2, const uint8_t *addr1, const uint8_t *addr2,
const uint8_t *nonce1, const uint8_t *nonce2, const uint8_t *nonce1, const uint8_t *nonce2,
struct crypto_ptk *out_ptk, size_t ptk_len, uint8_t *out_ptk, size_t ptk_len,
bool use_sha256); bool use_sha256);
bool crypto_derive_pmk_r0(const uint8_t *xxkey, bool crypto_derive_pmk_r0(const uint8_t *xxkey,
@ -121,7 +115,7 @@ bool crypto_derive_pmk_r1(const uint8_t *pmk_r0,
bool crypto_derive_ft_ptk(const uint8_t *pmk_r1, const uint8_t *pmk_r1_name, bool crypto_derive_ft_ptk(const uint8_t *pmk_r1, const uint8_t *pmk_r1_name,
const uint8_t *addr1, const uint8_t *addr2, const uint8_t *addr1, const uint8_t *addr2,
const uint8_t *nonce1, const uint8_t *nonce2, const uint8_t *nonce1, const uint8_t *nonce2,
struct crypto_ptk *out_ptk, size_t ptk_len, uint8_t *out_ptk, size_t ptk_len,
uint8_t *out_ptk_name); uint8_t *out_ptk_name);
bool crypto_derive_pmkid(const uint8_t *pmk, bool crypto_derive_pmkid(const uint8_t *pmk,

View File

@ -226,7 +226,7 @@ uint8_t *eapol_decrypt_key_data(enum ie_rsn_akm_suite akm, const uint8_t *kek,
case EAPOL_KEY_DESCRIPTOR_VERSION_HMAC_SHA1_AES: case EAPOL_KEY_DESCRIPTOR_VERSION_HMAC_SHA1_AES:
case EAPOL_KEY_DESCRIPTOR_VERSION_AES_128_CMAC_AES: case EAPOL_KEY_DESCRIPTOR_VERSION_AES_128_CMAC_AES:
case EAPOL_KEY_DESCRIPTOR_VERSION_AKM_DEFINED: case EAPOL_KEY_DESCRIPTOR_VERSION_AKM_DEFINED:
if (!aes_unwrap(kek, key_data, key_data_len, buf)) if (!aes_unwrap(kek, 16, key_data, key_data_len, buf))
goto error; goto error;
break; break;
@ -960,7 +960,7 @@ static void eapol_ptk_1_of_4_retry(struct l_timeout *timeout, void *user_data)
static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm, static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
const struct eapol_key *ek) const struct eapol_key *ek)
{ {
const struct crypto_ptk *ptk; const uint8_t *kck;
struct eapol_key *step2; struct eapol_key *step2;
uint8_t mic[MIC_MAXLEN]; uint8_t mic[MIC_MAXLEN];
uint8_t *ies; uint8_t *ies;
@ -1084,9 +1084,9 @@ static void eapol_handle_ptk_1_of_4(struct eapol_sm *sm,
sm->handshake->snonce, ies_len, ies, sm->handshake->snonce, ies_len, ies,
sm->handshake->wpa_ie, sm->mic_len); sm->handshake->wpa_ie, sm->mic_len);
ptk = handshake_state_get_ptk(sm->handshake); kck = handshake_state_get_kck(sm->handshake);
if (!eapol_calculate_mic(sm->handshake->akm_suite, ptk->kck, if (!eapol_calculate_mic(sm->handshake->akm_suite, kck,
step2, mic, sm->mic_len)) { step2, mic, sm->mic_len)) {
l_info("MIC calculation failed. " l_info("MIC calculation failed. "
"Ensure Kernel Crypto is available."); "Ensure Kernel Crypto is available.");
@ -1123,7 +1123,8 @@ static void eapol_send_ptk_3_of_4(struct eapol_sm *sm)
sm->handshake->pairwise_cipher); sm->handshake->pairwise_cipher);
enum crypto_cipher group_cipher = ie_rsn_cipher_suite_to_cipher( enum crypto_cipher group_cipher = ie_rsn_cipher_suite_to_cipher(
sm->handshake->group_cipher); sm->handshake->group_cipher);
const struct crypto_ptk *ptk = (struct crypto_ptk *) sm->handshake->ptk; const uint8_t *kck;
const uint8_t *kek;
struct ie_rsn_info rsn; struct ie_rsn_info rsn;
uint8_t *rsne; uint8_t *rsne;
@ -1174,7 +1175,9 @@ static void eapol_send_ptk_3_of_4(struct eapol_sm *sm)
key_data_len += gtk_kde[1] + 2; key_data_len += gtk_kde[1] + 2;
} }
if (!eapol_encrypt_key_data(ptk->kek, key_data_buf, kek = handshake_state_get_kek(sm->handshake);
if (!eapol_encrypt_key_data(kek, key_data_buf,
key_data_len, ek, sm->mic_len)) key_data_len, ek, sm->mic_len))
return; return;
@ -1183,7 +1186,9 @@ static void eapol_send_ptk_3_of_4(struct eapol_sm *sm)
ek->header.packet_len = L_CPU_TO_BE16(EAPOL_FRAME_LEN(sm->mic_len) + ek->header.packet_len = L_CPU_TO_BE16(EAPOL_FRAME_LEN(sm->mic_len) +
key_data_len - 4); key_data_len - 4);
if (!eapol_calculate_mic(sm->handshake->akm_suite, ptk->kck, ek, kck = handshake_state_get_kck(sm->handshake);
if (!eapol_calculate_mic(sm->handshake->akm_suite, kck, ek,
EAPOL_KEY_MIC(ek), sm->mic_len)) EAPOL_KEY_MIC(ek), sm->mic_len))
return; return;
@ -1242,10 +1247,8 @@ static void eapol_handle_ptk_2_of_4(struct eapol_sm *sm,
const struct eapol_key *ek) const struct eapol_key *ek)
{ {
const uint8_t *rsne; const uint8_t *rsne;
enum crypto_cipher cipher;
size_t ptk_size; size_t ptk_size;
uint8_t ptk_buf[64]; const uint8_t *kck;
struct crypto_ptk *ptk = (struct crypto_ptk *) ptk_buf;
const uint8_t *aa = sm->handshake->aa; const uint8_t *aa = sm->handshake->aa;
l_debug("ifindex=%u", sm->handshake->ifindex); l_debug("ifindex=%u", sm->handshake->ifindex);
@ -1256,15 +1259,17 @@ static void eapol_handle_ptk_2_of_4(struct eapol_sm *sm,
if (L_BE64_TO_CPU(ek->key_replay_counter) != sm->replay_counter) if (L_BE64_TO_CPU(ek->key_replay_counter) != sm->replay_counter)
return; return;
cipher = ie_rsn_cipher_suite_to_cipher(sm->handshake->pairwise_cipher); ptk_size = handshake_state_get_ptk_size(sm->handshake);
ptk_size = sizeof(struct crypto_ptk) + crypto_cipher_key_len(cipher);
if (!crypto_derive_pairwise_ptk(sm->handshake->pmk, sm->handshake->spa, if (!crypto_derive_pairwise_ptk(sm->handshake->pmk,
aa, sm->handshake->anonce, sm->handshake->spa, aa,
ek->key_nonce, ptk, ptk_size, false)) sm->handshake->anonce, ek->key_nonce,
sm->handshake->ptk, ptk_size, false))
return; return;
if (!eapol_verify_mic(sm->handshake->akm_suite, ptk->kck, ek, kck = handshake_state_get_kck(sm->handshake);
if (!eapol_verify_mic(sm->handshake->akm_suite, kck, ek,
sm->mic_len)) sm->mic_len))
return; return;
@ -1282,7 +1287,6 @@ static void eapol_handle_ptk_2_of_4(struct eapol_sm *sm,
return; return;
} }
memcpy(sm->handshake->ptk, ptk_buf, ptk_size);
memcpy(sm->handshake->snonce, ek->key_nonce, memcpy(sm->handshake->snonce, ek->key_nonce,
sizeof(sm->handshake->snonce)); sizeof(sm->handshake->snonce));
sm->handshake->have_snonce = true; sm->handshake->have_snonce = true;
@ -1316,7 +1320,8 @@ static void eapol_handle_ptk_3_of_4(struct eapol_sm *sm,
const uint8_t *decrypted_key_data, const uint8_t *decrypted_key_data,
size_t decrypted_key_data_size) size_t decrypted_key_data_size)
{ {
const struct crypto_ptk *ptk; const uint8_t *kck;
const uint8_t *kek;
struct eapol_key *step4; struct eapol_key *step4;
uint8_t mic[MIC_MAXLEN]; uint8_t mic[MIC_MAXLEN];
const uint8_t *gtk = NULL; const uint8_t *gtk = NULL;
@ -1516,9 +1521,10 @@ retransmit:
sm->replay_counter, sm->replay_counter,
sm->handshake->wpa_ie, sm->mic_len); sm->handshake->wpa_ie, sm->mic_len);
ptk = handshake_state_get_ptk(sm->handshake); kck = handshake_state_get_kck(sm->handshake);
kek = handshake_state_get_kek(sm->handshake);
if (!eapol_calculate_mic(sm->handshake->akm_suite, ptk->kck, if (!eapol_calculate_mic(sm->handshake->akm_suite, kck,
step4, mic, sm->mic_len)) { step4, mic, sm->mic_len)) {
l_free(step4); l_free(step4);
handshake_failed(sm, MMPDU_REASON_CODE_UNSPECIFIED); handshake_failed(sm, MMPDU_REASON_CODE_UNSPECIFIED);
@ -1550,7 +1556,7 @@ retransmit:
handshake_state_install_ptk(sm->handshake); handshake_state_install_ptk(sm->handshake);
if (rekey_offload) if (rekey_offload)
rekey_offload(sm->handshake->ifindex, ptk->kek, ptk->kck, rekey_offload(sm->handshake->ifindex, kek, kck,
sm->replay_counter, sm->user_data); sm->replay_counter, sm->user_data);
l_timeout_remove(sm->timeout); l_timeout_remove(sm->timeout);
@ -1566,7 +1572,7 @@ error_ie_different:
static void eapol_handle_ptk_4_of_4(struct eapol_sm *sm, static void eapol_handle_ptk_4_of_4(struct eapol_sm *sm,
const struct eapol_key *ek) const struct eapol_key *ek)
{ {
const struct crypto_ptk *ptk = (struct crypto_ptk *) sm->handshake->ptk; const uint8_t *kck;
l_debug("ifindex=%u", sm->handshake->ifindex); l_debug("ifindex=%u", sm->handshake->ifindex);
@ -1576,7 +1582,9 @@ static void eapol_handle_ptk_4_of_4(struct eapol_sm *sm,
if (L_BE64_TO_CPU(ek->key_replay_counter) != sm->replay_counter) if (L_BE64_TO_CPU(ek->key_replay_counter) != sm->replay_counter)
return; return;
if (!eapol_verify_mic(sm->handshake->akm_suite, ptk->kck, ek, kck = handshake_state_get_kck(sm->handshake);
if (!eapol_verify_mic(sm->handshake->akm_suite, kck, ek,
sm->mic_len)) sm->mic_len))
return; return;
@ -1591,7 +1599,7 @@ static void eapol_handle_gtk_1_of_2(struct eapol_sm *sm,
const uint8_t *decrypted_key_data, const uint8_t *decrypted_key_data,
size_t decrypted_key_data_size) size_t decrypted_key_data_size)
{ {
const struct crypto_ptk *ptk; const uint8_t *kck;
struct eapol_key *step2; struct eapol_key *step2;
uint8_t mic[MIC_MAXLEN]; uint8_t mic[MIC_MAXLEN];
const uint8_t *gtk; const uint8_t *gtk;
@ -1664,9 +1672,9 @@ static void eapol_handle_gtk_1_of_2(struct eapol_sm *sm,
sm->handshake->wpa_ie, ek->wpa_key_id, sm->handshake->wpa_ie, ek->wpa_key_id,
sm->mic_len); sm->mic_len);
ptk = handshake_state_get_ptk(sm->handshake); kck = handshake_state_get_kck(sm->handshake);
if (!eapol_calculate_mic(sm->handshake->akm_suite, ptk->kck, if (!eapol_calculate_mic(sm->handshake->akm_suite, kck,
step2, mic, sm->mic_len)) { step2, mic, sm->mic_len)) {
l_free(step2); l_free(step2);
handshake_failed(sm, MMPDU_REASON_CODE_UNSPECIFIED); handshake_failed(sm, MMPDU_REASON_CODE_UNSPECIFIED);
@ -1708,7 +1716,8 @@ static void eapol_key_handle(struct eapol_sm *sm,
const struct eapol_frame *frame) const struct eapol_frame *frame)
{ {
const struct eapol_key *ek; const struct eapol_key *ek;
const struct crypto_ptk *ptk; const uint8_t *kck;
const uint8_t *kek;
uint8_t *decrypted_key_data = NULL; uint8_t *decrypted_key_data = NULL;
size_t key_data_len = 0; size_t key_data_len = 0;
uint64_t replay_counter; uint64_t replay_counter;
@ -1761,14 +1770,14 @@ static void eapol_key_handle(struct eapol_sm *sm,
if (sm->have_replay && sm->replay_counter >= replay_counter) if (sm->have_replay && sm->replay_counter >= replay_counter)
return; return;
ptk = handshake_state_get_ptk(sm->handshake); kck = handshake_state_get_kck(sm->handshake);
if (ek->key_mic) { if (ek->key_mic) {
/* Haven't received step 1 yet, so no ptk */ /* Haven't received step 1 yet, so no ptk */
if (!sm->handshake->have_snonce) if (!sm->handshake->have_snonce)
return; return;
if (!eapol_verify_mic(sm->handshake->akm_suite, ptk->kck, ek, if (!eapol_verify_mic(sm->handshake->akm_suite, kck, ek,
sm->mic_len)) sm->mic_len))
return; return;
} }
@ -1779,8 +1788,10 @@ static void eapol_key_handle(struct eapol_sm *sm,
if (!sm->handshake->have_snonce) if (!sm->handshake->have_snonce)
return; return;
kek = handshake_state_get_kek(sm->handshake);
decrypted_key_data = eapol_decrypt_key_data( decrypted_key_data = eapol_decrypt_key_data(
sm->handshake->akm_suite, ptk->kek, sm->handshake->akm_suite, kek,
ek, &key_data_len, sm->mic_len); ek, &key_data_len, sm->mic_len);
if (!decrypted_key_data) if (!decrypted_key_data)
return; return;

View File

@ -44,7 +44,7 @@ bool ft_calculate_fte_mic(struct handshake_state *hs, uint8_t seq_num,
struct iovec iov[10]; struct iovec iov[10];
int iov_elems = 0; int iov_elems = 0;
struct l_checksum *checksum; struct l_checksum *checksum;
const struct crypto_ptk *ptk = handshake_state_get_ptk(hs); const uint8_t *kck = handshake_state_get_kck(hs);
uint8_t zero_mic[16] = {}; uint8_t zero_mic[16] = {};
iov[iov_elems].iov_base = hs->spa; iov[iov_elems].iov_base = hs->spa;
@ -80,7 +80,7 @@ bool ft_calculate_fte_mic(struct handshake_state *hs, uint8_t seq_num,
iov[iov_elems++].iov_len = ric[1] + 2; iov[iov_elems++].iov_len = ric[1] + 2;
} }
checksum = l_checksum_new_cmac_aes(ptk->kck, 16); checksum = l_checksum_new_cmac_aes(kck, 16);
if (!checksum) if (!checksum)
return false; return false;

View File

@ -278,10 +278,51 @@ void handshake_state_set_anonce(struct handshake_state *s,
memcpy(s->anonce, anonce, 32); memcpy(s->anonce, anonce, 32);
} }
/* A multi-purpose getter for key sizes */
static bool handshake_get_key_sizes(struct handshake_state *s, size_t *ptk_size,
size_t *kck_size, size_t *kek_size)
{
size_t kck;
size_t kek;
size_t tk;
enum crypto_cipher cipher =
ie_rsn_cipher_suite_to_cipher(s->pairwise_cipher);
tk = crypto_cipher_key_len(cipher);
/*
* IEEE 802.11-2016 Table 12-8: Integrity and key-wrap algorithms
*
* From the table, only 00-0F-AC:12 and 00-0F-AC:13 use longer KCK and
* KEK keys, which are 24 and 32 bytes respectively. The remainder use
* 16 and 16 respectively.
*/
switch (s->akm_suite) {
case IE_RSN_AKM_SUITE_8021X_SUITE_B_SHA256:
case IE_RSN_AKM_SUITE_FT_OVER_8021X_SHA384:
kck = 24;
kek = 32;
break;
default:
kck = 16;
kek = 16;
break;
}
if (ptk_size)
*ptk_size = kck + kek + tk;
if (kck_size)
*kck_size = kck;
if (kek_size)
*kek_size = kek;
return true;
}
bool handshake_state_derive_ptk(struct handshake_state *s) bool handshake_state_derive_ptk(struct handshake_state *s)
{ {
struct crypto_ptk *ptk = (struct crypto_ptk *) s->ptk;
enum crypto_cipher cipher;
size_t ptk_size; size_t ptk_size;
bool use_sha256; bool use_sha256;
@ -305,9 +346,7 @@ bool handshake_state_derive_ptk(struct handshake_state *s)
else else
use_sha256 = false; use_sha256 = false;
cipher = ie_rsn_cipher_suite_to_cipher(s->pairwise_cipher); ptk_size = handshake_state_get_ptk_size(s);
ptk_size = sizeof(struct crypto_ptk) + crypto_cipher_key_len(cipher);
if (s->akm_suite & (IE_RSN_AKM_SUITE_FT_OVER_8021X | if (s->akm_suite & (IE_RSN_AKM_SUITE_FT_OVER_8021X |
IE_RSN_AKM_SUITE_FT_USING_PSK | IE_RSN_AKM_SUITE_FT_USING_PSK |
@ -344,26 +383,54 @@ bool handshake_state_derive_ptk(struct handshake_state *s)
if (!crypto_derive_ft_ptk(s->pmk_r1, s->pmk_r1_name, s->aa, if (!crypto_derive_ft_ptk(s->pmk_r1, s->pmk_r1_name, s->aa,
s->spa, s->snonce, s->anonce, s->spa, s->snonce, s->anonce,
ptk, ptk_size, ptk_name)) s->ptk, ptk_size, ptk_name))
return false; return false;
} else } else
if (!crypto_derive_pairwise_ptk(s->pmk, s->spa, s->aa, if (!crypto_derive_pairwise_ptk(s->pmk, s->spa,
s->anonce, s->snonce, s->aa, s->anonce, s->snonce,
ptk, ptk_size, use_sha256)) s->ptk, ptk_size, use_sha256))
return false; return false;
return true; return true;
} }
const struct crypto_ptk *handshake_state_get_ptk(struct handshake_state *s) size_t handshake_state_get_ptk_size(struct handshake_state *s)
{ {
return (struct crypto_ptk *) s->ptk; size_t ptk_size;
if (!handshake_get_key_sizes(s, &ptk_size, NULL, NULL))
return 0;
return ptk_size;
}
const uint8_t *handshake_state_get_kck(struct handshake_state *s)
{
return s->ptk;
}
const uint8_t *handshake_state_get_kek(struct handshake_state *s)
{
size_t kck_size;
if (!handshake_get_key_sizes(s, NULL, &kck_size, NULL))
return NULL;
return s->ptk + kck_size;
}
static const uint8_t *handshake_get_tk(struct handshake_state *s)
{
size_t kck_size, kek_size;
if (!handshake_get_key_sizes(s, NULL, &kck_size, &kek_size))
return NULL;
return s->ptk + kck_size + kek_size;
} }
void handshake_state_install_ptk(struct handshake_state *s) void handshake_state_install_ptk(struct handshake_state *s)
{ {
struct crypto_ptk *ptk = (struct crypto_ptk *) s->ptk;
s->ptk_complete = true; s->ptk_complete = true;
if (install_tk) { if (install_tk) {
@ -372,7 +439,7 @@ void handshake_state_install_ptk(struct handshake_state *s)
handshake_event(s, HANDSHAKE_EVENT_SETTING_KEYS, NULL); handshake_event(s, HANDSHAKE_EVENT_SETTING_KEYS, NULL);
install_tk(s, ptk->tk, cipher); install_tk(s, handshake_get_tk(s), cipher);
} }
} }
@ -684,10 +751,10 @@ void handshake_util_build_gtk_kde(enum crypto_cipher cipher, const uint8_t *key,
bool handshake_decode_fte_key(struct handshake_state *s, const uint8_t *wrapped, bool handshake_decode_fte_key(struct handshake_state *s, const uint8_t *wrapped,
size_t key_len, uint8_t *key_out) size_t key_len, uint8_t *key_out)
{ {
const struct crypto_ptk *ptk = handshake_state_get_ptk(s); const uint8_t *kek = handshake_state_get_kek(s);
size_t padded_len = key_len < 16 ? 16 : align_len(key_len, 8); size_t padded_len = key_len < 16 ? 16 : align_len(key_len, 8);
if (!aes_unwrap(ptk->kek, wrapped, padded_len + 8, key_out)) if (!aes_unwrap(kek, 16, wrapped, padded_len + 8, key_out))
return false; return false;
if (key_len < padded_len && key_out[key_len++] != 0xdd) if (key_len < padded_len && key_out[key_len++] != 0xdd)

View File

@ -90,7 +90,7 @@ struct handshake_state {
size_t pmk_len; size_t pmk_len;
uint8_t snonce[32]; uint8_t snonce[32];
uint8_t anonce[32]; uint8_t anonce[32];
uint8_t ptk[64]; uint8_t ptk[80];
uint8_t pmk_r0[32]; uint8_t pmk_r0[32];
uint8_t pmk_r0_name[16]; uint8_t pmk_r0_name[16];
uint8_t pmk_r1[32]; uint8_t pmk_r1[32];
@ -164,7 +164,9 @@ void handshake_state_set_anonce(struct handshake_state *s,
const uint8_t *anonce); const uint8_t *anonce);
void handshake_state_set_pmkid(struct handshake_state *s, const uint8_t *pmkid); void handshake_state_set_pmkid(struct handshake_state *s, const uint8_t *pmkid);
bool handshake_state_derive_ptk(struct handshake_state *s); bool handshake_state_derive_ptk(struct handshake_state *s);
const struct crypto_ptk *handshake_state_get_ptk(struct handshake_state *s); size_t handshake_state_get_ptk_size(struct handshake_state *s);
const uint8_t *handshake_state_get_kck(struct handshake_state *s);
const uint8_t *handshake_state_get_kek(struct handshake_state *s);
void handshake_state_install_ptk(struct handshake_state *s); void handshake_state_install_ptk(struct handshake_state *s);
void handshake_state_install_gtk(struct handshake_state *s, void handshake_state_install_gtk(struct handshake_state *s,