RSN authenticator: Use os_memcmp_const() for hash/password comparisons

This makes the implementation less likely to provide useful timing
information to potential attackers from comparisons of information
received from a remote device and private material known only by the
authorized devices.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2014-06-29 20:15:37 +03:00
parent 0d15b69f0a
commit 870834a19b
2 changed files with 22 additions and 19 deletions

View file

@ -1490,7 +1490,7 @@ static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len)
os_memset(key->key_mic, 0, 16); os_memset(key->key_mic, 0, 16);
if (wpa_eapol_key_mic(PTK->kck, key_info & WPA_KEY_INFO_TYPE_MASK, if (wpa_eapol_key_mic(PTK->kck, key_info & WPA_KEY_INFO_TYPE_MASK,
data, data_len, key->key_mic) || data, data_len, key->key_mic) ||
os_memcmp(mic, key->key_mic, 16) != 0) os_memcmp_const(mic, key->key_mic, 16) != 0)
ret = -1; ret = -1;
os_memcpy(key->key_mic, mic, 16); os_memcpy(key->key_mic, mic, 16);
return ret; return ret;
@ -1877,8 +1877,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
* Verify that PMKR1Name from EAPOL-Key message 2/4 matches * Verify that PMKR1Name from EAPOL-Key message 2/4 matches
* with the value we derived. * with the value we derived.
*/ */
if (os_memcmp(sm->sup_pmk_r1_name, sm->pmk_r1_name, if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name,
WPA_PMK_NAME_LEN) != 0) { WPA_PMK_NAME_LEN) != 0) {
wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
"PMKR1Name mismatch in FT 4-way " "PMKR1Name mismatch in FT 4-way "
"handshake"); "handshake");

View file

@ -235,8 +235,8 @@ static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth,
r0 = cache->pmk_r0; r0 = cache->pmk_r0;
while (r0) { while (r0) {
if (os_memcmp(r0->spa, spa, ETH_ALEN) == 0 && if (os_memcmp(r0->spa, spa, ETH_ALEN) == 0 &&
os_memcmp(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN) os_memcmp_const(r0->pmk_r0_name, pmk_r0_name,
== 0) { WPA_PMK_NAME_LEN) == 0) {
os_memcpy(pmk_r0, r0->pmk_r0, PMK_LEN); os_memcpy(pmk_r0, r0->pmk_r0, PMK_LEN);
if (pairwise) if (pairwise)
*pairwise = r0->pairwise; *pairwise = r0->pairwise;
@ -285,8 +285,8 @@ static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth,
r1 = cache->pmk_r1; r1 = cache->pmk_r1;
while (r1) { while (r1) {
if (os_memcmp(r1->spa, spa, ETH_ALEN) == 0 && if (os_memcmp(r1->spa, spa, ETH_ALEN) == 0 &&
os_memcmp(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN) os_memcmp_const(r1->pmk_r1_name, pmk_r1_name,
== 0) { WPA_PMK_NAME_LEN) == 0) {
os_memcpy(pmk_r1, r1->pmk_r1, PMK_LEN); os_memcpy(pmk_r1, r1->pmk_r1, PMK_LEN);
if (pairwise) if (pairwise)
*pairwise = r1->pairwise; *pairwise = r1->pairwise;
@ -310,7 +310,8 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
r0kh = sm->wpa_auth->conf.r0kh_list; r0kh = sm->wpa_auth->conf.r0kh_list;
while (r0kh) { while (r0kh) {
if (r0kh->id_len == sm->r0kh_id_len && if (r0kh->id_len == sm->r0kh_id_len &&
os_memcmp(r0kh->id, sm->r0kh_id, sm->r0kh_id_len) == 0) os_memcmp_const(r0kh->id, sm->r0kh_id, sm->r0kh_id_len) ==
0)
break; break;
r0kh = r0kh->next; r0kh = r0kh->next;
} }
@ -1013,8 +1014,8 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
return WLAN_STATUS_INVALID_PMKID; return WLAN_STATUS_INVALID_PMKID;
} }
if (os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) if (os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)
{ != 0) {
wpa_printf(MSG_DEBUG, "FT: PMKID in Reassoc Req did not match " wpa_printf(MSG_DEBUG, "FT: PMKID in Reassoc Req did not match "
"with the PMKR1Name derived from auth request"); "with the PMKR1Name derived from auth request");
return WLAN_STATUS_INVALID_PMKID; return WLAN_STATUS_INVALID_PMKID;
@ -1060,7 +1061,8 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
} }
if (parse.r0kh_id_len != sm->r0kh_id_len || if (parse.r0kh_id_len != sm->r0kh_id_len ||
os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) { os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
{
wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with " wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
"the current R0KH-ID"); "the current R0KH-ID");
wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE", wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
@ -1075,8 +1077,8 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
return -1; return -1;
} }
if (os_memcmp(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder, if (os_memcmp_const(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder,
FT_R1KH_ID_LEN) != 0) { FT_R1KH_ID_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in " wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
"ReassocReq"); "ReassocReq");
wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID in FTIE", wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID in FTIE",
@ -1087,7 +1089,8 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
} }
if (parse.rsn_pmkid == NULL || if (parse.rsn_pmkid == NULL ||
os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)) { os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN))
{
wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in " wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
"RSNIE (pmkid=%d)", !!parse.rsn_pmkid); "RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
return -1; return -1;
@ -1113,7 +1116,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
return WLAN_STATUS_UNSPECIFIED_FAILURE; return WLAN_STATUS_UNSPECIFIED_FAILURE;
} }
if (os_memcmp(mic, ftie->mic, 16) != 0) { if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE"); wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR, wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR,
MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr)); MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr));
@ -1468,8 +1471,8 @@ static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
return -1; return -1;
} }
if (os_memcmp(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN) if (os_memcmp_const(f.r1kh_id, wpa_auth->conf.r1_key_holder,
!= 0) { FT_R1KH_ID_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull response did not use a " wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull response did not use a "
"matching R1KH-ID"); "matching R1KH-ID");
return -1; return -1;
@ -1544,8 +1547,8 @@ static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
return -1; return -1;
} }
if (os_memcmp(f.r1kh_id, wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN) if (os_memcmp_const(f.r1kh_id, wpa_auth->conf.r1_key_holder,
!= 0) { FT_R1KH_ID_LEN) != 0) {
wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not use a matching " wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not use a matching "
"R1KH-ID (received " MACSTR " own " MACSTR ")", "R1KH-ID (received " MACSTR " own " MACSTR ")",
MAC2STR(f.r1kh_id), MAC2STR(f.r1kh_id),