}
-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;
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");
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;
}
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 */
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);
}
}
const u8 **realm, size_t *realm_len, u16 *erp_seq_num,
const u8 **rrk, size_t *rrk_len);
int eap_peer_update_erp_next_seq_num(struct eap_sm *sm, u16 seq_num);
+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);
#endif /* IEEE8021X_EAPOL */
#include "crypto/md5.h"
#include "common/eapol_common.h"
#include "eap_peer/eap.h"
+#include "eap_peer/eap_config.h"
#include "eap_peer/eap_proxy.h"
#include "eapol_supp_sm.h"
#ifdef CONFIG_EAP_PROXY
if (sm->use_eap_proxy) {
if (eap_proxy_key_available(sm->eap_proxy)) {
+ u8 *session_id, *emsk;
+ size_t session_id_len, emsk_len;
+
/* New key received - clear IEEE 802.1X EAPOL-Key replay
* counter */
sm->replay_counter_valid = FALSE;
+
+ session_id = eap_proxy_get_eap_session_id(
+ sm->eap_proxy, &session_id_len);
+ emsk = eap_proxy_get_emsk(sm->eap_proxy, &emsk_len);
+ if (sm->config->erp && session_id && emsk)
+ eap_peer_erp_init(sm->eap, session_id,
+ session_id_len, emsk,
+ emsk_len);
}
return;
}
wpabuf_free(sm->eapReqData);
sm->eapReqData = NULL;
eap_sm_abort(sm->eap);
+#ifdef CONFIG_EAP_PROXY
+ eap_proxy_sm_abort(sm->eap_proxy);
+#endif /* CONFIG_EAP_PROXY */
}