]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
eap_proxy: Add support for deriving ERP information
authorVidyullatha Kanchanapally <vkanchan@qti.qualcomm.com>
Mon, 15 May 2017 14:28:25 +0000 (19:58 +0530)
committerJouni Malinen <j@w1.fi>
Mon, 5 Jun 2017 05:04:52 +0000 (08:04 +0300)
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>
src/eap_peer/eap.c
src/eap_peer/eap.h
src/eap_peer/eap_proxy.h
src/eap_peer/eap_proxy_dummy.c
src/eapol_supp/eapol_supp_sm.c

index 28bb0442a53c635eeffa149c26dfab6da58440f4..359701c373c36dbd4fbf764b0b515b07115bc7da 100644 (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;
 
-       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);
        }
 }
 
index 883ba242330a595eb96cbbfc6b436be406ae275a..80fbbf260a5f08b21761f175720b2e5450ed65af 100644 (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 */
 
index 7205fad44949d9f3cb0bd50c16c2485a7c8d5fce..95fd71f3c7f8025b9d2e88222eb50cbeb97f33ee 100644 (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 */
index 08009cab24cb1a1a94fcb7ad8b4d1750027c4f46..0cf647a5581f6c7cd3ba3cd482e6d98eae117f07 100644 (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)
+{
+}
index 81761b1895103ef4a409565edf4174f1b761da77..ade43d8ef62226ccf281cf6e55bbba49e0303740 100644 (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 */
 }