|
@@ -568,11 +568,15 @@ void eap_peer_erp_free_keys(struct eap_sm *sm)
|
|
|
}
|
|
|
|
|
|
|
|
|
-static void eap_peer_erp_init(struct eap_sm *sm)
|
|
|
+void eap_peer_erp_init(struct eap_sm *sm, u8 *ext_session_id,
|
|
|
+ size_t ext_session_id_len, u8 *ext_emsk,
|
|
|
+ size_t ext_emsk_len)
|
|
|
{
|
|
|
#ifdef CONFIG_ERP
|
|
|
u8 *emsk = NULL;
|
|
|
size_t emsk_len = 0;
|
|
|
+ u8 *session_id = NULL;
|
|
|
+ size_t session_id_len = 0;
|
|
|
u8 EMSKname[EAP_EMSK_NAME_LEN];
|
|
|
u8 len[2], ctx[3];
|
|
|
char *realm;
|
|
@@ -602,7 +606,13 @@ static void eap_peer_erp_init(struct eap_sm *sm)
|
|
|
if (erp == NULL)
|
|
|
goto fail;
|
|
|
|
|
|
- emsk = sm->m->get_emsk(sm, sm->eap_method_priv, &emsk_len);
|
|
|
+ if (ext_emsk) {
|
|
|
+ emsk = ext_emsk;
|
|
|
+ emsk_len = ext_emsk_len;
|
|
|
+ } else {
|
|
|
+ emsk = sm->m->get_emsk(sm, sm->eap_method_priv, &emsk_len);
|
|
|
+ }
|
|
|
+
|
|
|
if (!emsk || emsk_len == 0 || emsk_len > ERP_MAX_KEY_LEN) {
|
|
|
wpa_printf(MSG_DEBUG,
|
|
|
"EAP: No suitable EMSK available for ERP");
|
|
@@ -611,10 +621,23 @@ static void eap_peer_erp_init(struct eap_sm *sm)
|
|
|
|
|
|
wpa_hexdump_key(MSG_DEBUG, "EAP: EMSK", emsk, emsk_len);
|
|
|
|
|
|
+ if (ext_session_id) {
|
|
|
+ session_id = ext_session_id;
|
|
|
+ session_id_len = ext_session_id_len;
|
|
|
+ } else {
|
|
|
+ session_id = sm->eapSessionId;
|
|
|
+ session_id_len = sm->eapSessionIdLen;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!session_id || session_id_len == 0) {
|
|
|
+ wpa_printf(MSG_DEBUG,
|
|
|
+ "EAP: No suitable session id available for ERP");
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+
|
|
|
WPA_PUT_BE16(len, EAP_EMSK_NAME_LEN);
|
|
|
- if (hmac_sha256_kdf(sm->eapSessionId, sm->eapSessionIdLen, "EMSK",
|
|
|
- len, sizeof(len),
|
|
|
- EMSKname, EAP_EMSK_NAME_LEN) < 0) {
|
|
|
+ if (hmac_sha256_kdf(session_id, session_id_len, "EMSK", len,
|
|
|
+ sizeof(len), EMSKname, EAP_EMSK_NAME_LEN) < 0) {
|
|
|
wpa_printf(MSG_DEBUG, "EAP: Could not derive EMSKname");
|
|
|
goto fail;
|
|
|
}
|
|
@@ -651,6 +674,7 @@ static void eap_peer_erp_init(struct eap_sm *sm)
|
|
|
erp = NULL;
|
|
|
fail:
|
|
|
bin_clear_free(emsk, emsk_len);
|
|
|
+ bin_clear_free(ext_session_id, ext_session_id_len);
|
|
|
bin_clear_free(erp, sizeof(*erp));
|
|
|
os_free(realm);
|
|
|
#endif /* CONFIG_ERP */
|
|
@@ -807,7 +831,7 @@ SM_STATE(EAP, METHOD)
|
|
|
sm->eapSessionId, sm->eapSessionIdLen);
|
|
|
}
|
|
|
if (config->erp && sm->m->get_emsk && sm->eapSessionId)
|
|
|
- eap_peer_erp_init(sm);
|
|
|
+ eap_peer_erp_init(sm, NULL, 0, NULL, 0);
|
|
|
}
|
|
|
}
|
|
|
|