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:
parent
115d5e2221
commit
8696e61702
5 changed files with 71 additions and 6 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue