eap_proxy: Add support for deriving ERP information

This commit adds support for deriving ERP key information in EAP Proxy
based EAP method implementations.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Vidyullatha Kanchanapally 2017-05-15 19:58:25 +05:30 committed by Jouni Malinen
parent 115d5e2221
commit 8696e61702
5 changed files with 71 additions and 6 deletions

View file

@ -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;
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);
}
}

View file

@ -363,6 +363,9 @@ int eap_peer_get_erp_info(struct eap_sm *sm, struct eap_peer_config *config,
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 */

View file

@ -46,4 +46,10 @@ int eap_proxy_get_imsi(struct eap_proxy_sm *eap_proxy, char *imsi_buf,
int eap_proxy_notify_config(struct eap_proxy_sm *sm,
struct eap_peer_config *config);
u8 * eap_proxy_get_eap_session_id(struct eap_proxy_sm *sm, size_t *len);
u8 * eap_proxy_get_emsk(struct eap_proxy_sm *sm, size_t *len);
void eap_proxy_sm_abort(struct eap_proxy_sm *sm);
#endif /* EAP_PROXY_H */

View file

@ -75,3 +75,20 @@ int eap_proxy_notify_config(struct eap_proxy_sm *sm,
{
return -1;
}
u8 * eap_proxy_get_eap_session_id(struct eap_proxy_sm *sm, size_t *len)
{
return NULL;
}
u8 * eap_proxy_get_emsk(struct eap_proxy_sm *sm, size_t *len)
{
return NULL;
}
void eap_proxy_sm_abort(struct eap_proxy_sm *sm)
{
}

View file

@ -16,6 +16,7 @@
#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"
@ -492,9 +493,20 @@ SM_STATE(SUPP_BE, SUCCESS)
#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;
}
@ -899,6 +911,9 @@ static void eapol_sm_abortSupp(struct eapol_sm *sm)
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 */
}