EAP-SAKE: Report hash function failures to callers
While this is mostly theoretical, the hash functions can fail and it is better for the upper layer code to explicitly check for such failures. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
24b06511e2
commit
848718ddde
4 changed files with 82 additions and 53 deletions
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* EAP server/peer: EAP-SAKE shared routines
|
||||
* Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -201,11 +201,12 @@ int eap_sake_parse_attributes(const u8 *buf, size_t len,
|
|||
* @data2_len: Length of the data2
|
||||
* @buf: Buffer for the generated pseudo-random key
|
||||
* @buf_len: Number of bytes of key to generate
|
||||
* Returns: 0 on success or -1 on failure
|
||||
*
|
||||
* This function is used to derive new, cryptographically separate keys from a
|
||||
* given key (e.g., SMS). This is identical to the PRF used in IEEE 802.11i.
|
||||
*/
|
||||
static void eap_sake_kdf(const u8 *key, size_t key_len, const char *label,
|
||||
static int eap_sake_kdf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len,
|
||||
const u8 *data2, size_t data2_len,
|
||||
u8 *buf, size_t buf_len)
|
||||
|
@ -230,17 +231,21 @@ static void eap_sake_kdf(const u8 *key, size_t key_len, const char *label,
|
|||
while (pos < buf_len) {
|
||||
plen = buf_len - pos;
|
||||
if (plen >= SHA1_MAC_LEN) {
|
||||
hmac_sha1_vector(key, key_len, 4, addr, len,
|
||||
&buf[pos]);
|
||||
if (hmac_sha1_vector(key, key_len, 4, addr, len,
|
||||
&buf[pos]) < 0)
|
||||
return -1;
|
||||
pos += SHA1_MAC_LEN;
|
||||
} else {
|
||||
hmac_sha1_vector(key, key_len, 4, addr, len,
|
||||
hash);
|
||||
if (hmac_sha1_vector(key, key_len, 4, addr, len,
|
||||
hash) < 0)
|
||||
return -1;
|
||||
os_memcpy(&buf[pos], hash, plen);
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -253,10 +258,11 @@ static void eap_sake_kdf(const u8 *key, size_t key_len, const char *label,
|
|||
* @tek: Buffer for Temporary EAK Keys (TEK-Auth[16] | TEK-Cipher[16])
|
||||
* @msk: Buffer for 64-byte MSK
|
||||
* @emsk: Buffer for 64-byte EMSK
|
||||
* Returns: 0 on success or -1 on failure
|
||||
*
|
||||
* This function derives EAP-SAKE keys as defined in RFC 4763, section 3.2.6.
|
||||
*/
|
||||
void eap_sake_derive_keys(const u8 *root_secret_a, const u8 *root_secret_b,
|
||||
int eap_sake_derive_keys(const u8 *root_secret_a, const u8 *root_secret_b,
|
||||
const u8 *rand_s, const u8 *rand_p, u8 *tek, u8 *msk,
|
||||
u8 *emsk)
|
||||
{
|
||||
|
@ -268,14 +274,16 @@ void eap_sake_derive_keys(const u8 *root_secret_a, const u8 *root_secret_b,
|
|||
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: Root-Secret-A",
|
||||
root_secret_a, EAP_SAKE_ROOT_SECRET_LEN);
|
||||
eap_sake_kdf(root_secret_a, EAP_SAKE_ROOT_SECRET_LEN,
|
||||
if (eap_sake_kdf(root_secret_a, EAP_SAKE_ROOT_SECRET_LEN,
|
||||
"SAKE Master Secret A",
|
||||
rand_p, EAP_SAKE_RAND_LEN, rand_s, EAP_SAKE_RAND_LEN,
|
||||
sms_a, EAP_SAKE_SMS_LEN);
|
||||
sms_a, EAP_SAKE_SMS_LEN) < 0)
|
||||
return -1;
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: SMS-A", sms_a, EAP_SAKE_SMS_LEN);
|
||||
eap_sake_kdf(sms_a, EAP_SAKE_SMS_LEN, "Transient EAP Key",
|
||||
if (eap_sake_kdf(sms_a, EAP_SAKE_SMS_LEN, "Transient EAP Key",
|
||||
rand_s, EAP_SAKE_RAND_LEN, rand_p, EAP_SAKE_RAND_LEN,
|
||||
tek, EAP_SAKE_TEK_LEN);
|
||||
tek, EAP_SAKE_TEK_LEN) < 0)
|
||||
return -1;
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: TEK-Auth",
|
||||
tek, EAP_SAKE_TEK_AUTH_LEN);
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: TEK-Cipher",
|
||||
|
@ -283,18 +291,21 @@ void eap_sake_derive_keys(const u8 *root_secret_a, const u8 *root_secret_b,
|
|||
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: Root-Secret-B",
|
||||
root_secret_b, EAP_SAKE_ROOT_SECRET_LEN);
|
||||
eap_sake_kdf(root_secret_b, EAP_SAKE_ROOT_SECRET_LEN,
|
||||
if (eap_sake_kdf(root_secret_b, EAP_SAKE_ROOT_SECRET_LEN,
|
||||
"SAKE Master Secret B",
|
||||
rand_p, EAP_SAKE_RAND_LEN, rand_s, EAP_SAKE_RAND_LEN,
|
||||
sms_b, EAP_SAKE_SMS_LEN);
|
||||
sms_b, EAP_SAKE_SMS_LEN) < 0)
|
||||
return -1;
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: SMS-B", sms_b, EAP_SAKE_SMS_LEN);
|
||||
eap_sake_kdf(sms_b, EAP_SAKE_SMS_LEN, "Master Session Key",
|
||||
if (eap_sake_kdf(sms_b, EAP_SAKE_SMS_LEN, "Master Session Key",
|
||||
rand_s, EAP_SAKE_RAND_LEN, rand_p, EAP_SAKE_RAND_LEN,
|
||||
key_buf, sizeof(key_buf));
|
||||
key_buf, sizeof(key_buf)) < 0)
|
||||
return -1;
|
||||
os_memcpy(msk, key_buf, EAP_MSK_LEN);
|
||||
os_memcpy(emsk, key_buf + EAP_MSK_LEN, EAP_EMSK_LEN);
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: MSK", msk, EAP_MSK_LEN);
|
||||
wpa_hexdump_key(MSG_DEBUG, "EAP-SAKE: EMSK", emsk, EAP_EMSK_LEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -312,6 +323,7 @@ void eap_sake_derive_keys(const u8 *root_secret_a, const u8 *root_secret_b,
|
|||
* @eap_len: EAP packet length
|
||||
* @mic_pos: MIC position in the EAP packet (must be [eap .. eap + eap_len])
|
||||
* @mic: Buffer for the computed 16-byte MIC
|
||||
* Returns: 0 on success or -1 on failure
|
||||
*/
|
||||
int eap_sake_compute_mic(const u8 *tek_auth,
|
||||
const u8 *rand_s, const u8 *rand_p,
|
||||
|
@ -323,6 +335,7 @@ int eap_sake_compute_mic(const u8 *tek_auth,
|
|||
u8 _rand[2 * EAP_SAKE_RAND_LEN];
|
||||
u8 *tmp, *pos;
|
||||
size_t tmplen;
|
||||
int ret;
|
||||
|
||||
tmplen = serverid_len + 1 + peerid_len + 1 + eap_len;
|
||||
tmp = os_malloc(tmplen);
|
||||
|
@ -364,14 +377,14 @@ int eap_sake_compute_mic(const u8 *tek_auth,
|
|||
os_memcpy(pos, eap, eap_len);
|
||||
os_memset(pos + (mic_pos - eap), 0, EAP_SAKE_MIC_LEN);
|
||||
|
||||
eap_sake_kdf(tek_auth, EAP_SAKE_TEK_AUTH_LEN,
|
||||
ret = eap_sake_kdf(tek_auth, EAP_SAKE_TEK_AUTH_LEN,
|
||||
peer ? "Peer MIC" : "Server MIC",
|
||||
_rand, 2 * EAP_SAKE_RAND_LEN, tmp, tmplen,
|
||||
mic, EAP_SAKE_MIC_LEN);
|
||||
|
||||
os_free(tmp);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* EAP server/peer: EAP-SAKE shared routines
|
||||
* Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -81,7 +81,7 @@ struct eap_sake_parse_attr {
|
|||
|
||||
int eap_sake_parse_attributes(const u8 *buf, size_t len,
|
||||
struct eap_sake_parse_attr *attr);
|
||||
void eap_sake_derive_keys(const u8 *root_secret_a, const u8 *root_secret_b,
|
||||
int eap_sake_derive_keys(const u8 *root_secret_a, const u8 *root_secret_b,
|
||||
const u8 *rand_s, const u8 *rand_p,
|
||||
u8 *tek, u8 *msk, u8 *emsk);
|
||||
int eap_sake_compute_mic(const u8 *tek_auth,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* EAP peer method: EAP-SAKE (RFC 4763)
|
||||
* Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
|
||||
* Copyright (c) 2006-2019, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
|
@ -235,9 +235,13 @@ static struct wpabuf * eap_sake_process_challenge(struct eap_sm *sm,
|
|||
data->serverid_len = attr.serverid_len;
|
||||
}
|
||||
|
||||
eap_sake_derive_keys(data->root_secret_a, data->root_secret_b,
|
||||
if (eap_sake_derive_keys(data->root_secret_a, data->root_secret_b,
|
||||
data->rand_s, data->rand_p,
|
||||
(u8 *) &data->tek, data->msk, data->emsk);
|
||||
(u8 *) &data->tek, data->msk,
|
||||
data->emsk) < 0) {
|
||||
wpa_printf(MSG_INFO, "EAP-SAKE: Failed to derive keys");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Challenge");
|
||||
|
||||
|
|
|
@ -340,16 +340,25 @@ static void eap_sake_process_challenge(struct eap_sm *sm,
|
|||
data->state = FAILURE;
|
||||
return;
|
||||
}
|
||||
eap_sake_derive_keys(sm->user->password,
|
||||
if (eap_sake_derive_keys(sm->user->password,
|
||||
sm->user->password + EAP_SAKE_ROOT_SECRET_LEN,
|
||||
data->rand_s, data->rand_p,
|
||||
(u8 *) &data->tek, data->msk, data->emsk);
|
||||
(u8 *) &data->tek, data->msk,
|
||||
data->emsk) < 0) {
|
||||
wpa_printf(MSG_INFO, "EAP-SAKE: Failed to derive keys");
|
||||
data->state = FAILURE;
|
||||
return;
|
||||
}
|
||||
|
||||
eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p,
|
||||
if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p,
|
||||
sm->server_id, sm->server_id_len,
|
||||
data->peerid, data->peerid_len, 1,
|
||||
wpabuf_head(respData), wpabuf_len(respData),
|
||||
attr.mic_p, mic_p);
|
||||
attr.mic_p, mic_p) < 0) {
|
||||
wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC");
|
||||
data->state = FAILURE;
|
||||
return;
|
||||
}
|
||||
if (os_memcmp_const(attr.mic_p, mic_p, EAP_SAKE_MIC_LEN) != 0) {
|
||||
wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_P");
|
||||
eap_sake_state(data, FAILURE);
|
||||
|
@ -382,11 +391,14 @@ static void eap_sake_process_confirm(struct eap_sm *sm,
|
|||
return;
|
||||
}
|
||||
|
||||
eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p,
|
||||
if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p,
|
||||
sm->server_id, sm->server_id_len,
|
||||
data->peerid, data->peerid_len, 1,
|
||||
wpabuf_head(respData), wpabuf_len(respData),
|
||||
attr.mic_p, mic_p);
|
||||
attr.mic_p, mic_p) < 0) {
|
||||
wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC");
|
||||
return;
|
||||
}
|
||||
if (os_memcmp_const(attr.mic_p, mic_p, EAP_SAKE_MIC_LEN) != 0) {
|
||||
wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_P");
|
||||
eap_sake_state(data, FAILURE);
|
||||
|
|
Loading…
Reference in a new issue