Parcourir la source

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>
Vidyullatha Kanchanapally il y a 8 ans
Parent
commit
8696e61702

+ 30 - 6
src/eap_peer/eap.c

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

+ 3 - 0
src/eap_peer/eap.h

@@ -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 */
 

+ 6 - 0
src/eap_peer/eap_proxy.h

@@ -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 */

+ 17 - 0
src/eap_peer/eap_proxy_dummy.c

@@ -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)
+{
+}

+ 15 - 0
src/eapol_supp/eapol_supp_sm.c

@@ -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 */
 }