Skip to content

Commit bc3f4f1

Browse files
author
Mika Leppänen
committed
Added session message counter check to supplicant 4WH
Added check for message counter received on Message 1 to prevent problems when Message 1 is replayed to supplicant by lower layers. The PMK replay counter is not updated from Messsage 1 (which is unsecure), so the counter is 4WH session specific only.
1 parent d963915 commit bc3f4f1

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

source/Security/protocols/fwh_sec_prot/supp_fwh_sec_prot.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static int8_t supp_fwh_sec_prot_init(sec_prot_t *prot);
8686
static void supp_fwh_sec_prot_create_response(sec_prot_t *prot, sec_prot_result_e result);
8787
static void supp_fwh_sec_prot_delete(sec_prot_t *prot);
8888
static int8_t supp_fwh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t size);
89-
static fwh_sec_prot_msg_e supp_fwh_sec_prot_message_get(eapol_pdu_t *eapol_pdu, sec_prot_keys_t *sec_keys);
89+
static fwh_sec_prot_msg_e supp_fwh_sec_prot_message_get(sec_prot_t *prot, eapol_pdu_t *eapol_pdu);
9090
static void supp_fwh_sec_prot_state_machine(sec_prot_t *prot);
9191

9292
static int8_t supp_fwh_sec_prot_message_send(sec_prot_t *prot, fwh_sec_prot_msg_e msg);
@@ -96,6 +96,7 @@ static int8_t supp_fwh_sec_prot_ptk_generate(sec_prot_t *prot, sec_prot_keys_t *
9696
static int8_t supp_fwh_sec_prot_mic_validate(sec_prot_t *prot);
9797

9898
static void supp_fwh_sec_prot_recv_replay_counter_store(sec_prot_t *prot);
99+
static uint64_t supp_fwh_sec_prot_recv_replay_counter_get(sec_prot_t *prot);
99100
static void supp_fwh_sec_prot_anonce_store(sec_prot_t *prot);
100101
static int8_t supp_fwh_sec_prot_anonce_validate(sec_prot_t *prot);
101102
static void supp_fwh_sec_prot_security_replay_counter_update(sec_prot_t *prot);
@@ -137,6 +138,7 @@ static int8_t supp_fwh_sec_prot_init(sec_prot_t *prot)
137138

138139
data->common.ticks = 30 * 10; // 30 seconds
139140
data->msg3_retry_wait = false;
141+
data->recv_replay_cnt = 0;
140142

141143
uint8_t eui64[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
142144
sec_prot_lib_nonce_init(data->snonce, eui64, 1000);
@@ -167,7 +169,7 @@ static int8_t supp_fwh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t si
167169
// Decoding is successful
168170
if (eapol_parse_pdu_header(pdu, size, &data->recv_eapol_pdu)) {
169171
// Get message
170-
data->recv_msg = supp_fwh_sec_prot_message_get(&data->recv_eapol_pdu, prot->sec_keys);
172+
data->recv_msg = supp_fwh_sec_prot_message_get(prot, &data->recv_eapol_pdu);
171173
if (data->recv_msg != FWH_MESSAGE_UNKNOWN) {
172174
tr_info("4WH: recv %s", data->recv_msg == FWH_MESSAGE_1 ? "Message 1" : "Message 3");
173175

@@ -191,7 +193,7 @@ static int8_t supp_fwh_sec_prot_receive(sec_prot_t *prot, void *pdu, uint16_t si
191193
return ret_val;
192194
}
193195

194-
static fwh_sec_prot_msg_e supp_fwh_sec_prot_message_get(eapol_pdu_t *eapol_pdu, sec_prot_keys_t *sec_keys)
196+
static fwh_sec_prot_msg_e supp_fwh_sec_prot_message_get(sec_prot_t *prot, eapol_pdu_t *eapol_pdu)
195197
{
196198
fwh_sec_prot_msg_e msg = FWH_MESSAGE_UNKNOWN;
197199

@@ -203,17 +205,23 @@ static fwh_sec_prot_msg_e supp_fwh_sec_prot_message_get(eapol_pdu_t *eapol_pdu,
203205
uint8_t key_mask = sec_prot_lib_key_mask_get(eapol_pdu);
204206

205207
switch (key_mask) {
208+
// Message 1
206209
case KEY_INFO_KEY_ACK:
207-
// Must have valid replay counter
208-
if (eapol_pdu->msg.key.replay_counter > sec_prot_keys_pmk_replay_cnt_get(sec_keys)) {
210+
/* Must have valid replay counter, both larger for PMK and larger that is used on
211+
* the four way handshake session (note: PMK replay counter is not updated for Message 1
212+
* but session specific counter is)
213+
*/
214+
if (eapol_pdu->msg.key.replay_counter > sec_prot_keys_pmk_replay_cnt_get(prot->sec_keys) &&
215+
eapol_pdu->msg.key.replay_counter > supp_fwh_sec_prot_recv_replay_counter_get(prot)) {
209216
msg = FWH_MESSAGE_1;
210217
} else {
211218
tr_error("4WH: invalid replay counter %"PRId64, eapol_pdu->msg.key.replay_counter);
212219
}
213220
break;
221+
// Message 3
214222
case KEY_INFO_INSTALL | KEY_INFO_KEY_ACK | KEY_INFO_KEY_MIC | KEY_INFO_SECURED_KEY_FRAME:
215223
// Must have valid replay counter
216-
if (eapol_pdu->msg.key.replay_counter > sec_prot_keys_pmk_replay_cnt_get(sec_keys)) {
224+
if (eapol_pdu->msg.key.replay_counter > sec_prot_keys_pmk_replay_cnt_get(prot->sec_keys)) {
217225
if (eapol_pdu->msg.key.key_information.encrypted_key_data) {
218226
// This should include the GTK KDE, Lifetime KDE and GTKL KDE.
219227
// At least some of them should be present
@@ -468,6 +476,12 @@ static void supp_fwh_sec_prot_recv_replay_counter_store(sec_prot_t *prot)
468476
data->recv_replay_cnt = data->recv_eapol_pdu.msg.key.replay_counter;
469477
}
470478

479+
static uint64_t supp_fwh_sec_prot_recv_replay_counter_get(sec_prot_t *prot)
480+
{
481+
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);
482+
return data->recv_replay_cnt;
483+
}
484+
471485
static void supp_fwh_sec_prot_anonce_store(sec_prot_t *prot)
472486
{
473487
fwh_sec_prot_int_t *data = fwh_sec_prot_get(prot);

0 commit comments

Comments
 (0)