]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
ERP: External control of ERP key information
authorVidyullatha Kanchanapally <vkanchan@qti.qualcomm.com>
Wed, 22 Mar 2017 10:40:05 +0000 (16:10 +0530)
committerJouni Malinen <j@w1.fi>
Fri, 7 Apr 2017 15:46:13 +0000 (18:46 +0300)
This allows ERP keys to be managed by external entities, e.g., when
offloading FILS shared key authentication to a driver.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/eap_peer/eap.c
src/eap_peer/eap.h
src/eapol_supp/eapol_supp_sm.c
src/eapol_supp/eapol_supp_sm.h

index bc90c7af99214b1f15921f74c7a6af9e6f214f02..d0f305f1acb068d34497cd7359bd067afd534c1a 100644 (file)
@@ -371,9 +371,8 @@ nak:
 
 #ifdef CONFIG_ERP
 
-static char * eap_home_realm(struct eap_sm *sm)
+static char * eap_get_realm(struct eap_sm *sm, struct eap_peer_config *config)
 {
-       struct eap_peer_config *config = eap_get_config(sm);
        char *realm;
        size_t i, realm_len;
 
@@ -417,6 +416,12 @@ static char * eap_home_realm(struct eap_sm *sm)
 }
 
 
+static char * eap_home_realm(struct eap_sm *sm)
+{
+       return eap_get_realm(sm, eap_get_config(sm));
+}
+
+
 static struct eap_erp_key *
 eap_erp_get_key(struct eap_sm *sm, const char *realm)
 {
@@ -469,6 +474,84 @@ static void eap_erp_remove_keys_realm(struct eap_sm *sm, const char *realm)
        }
 }
 
+
+int eap_peer_update_erp_next_seq_num(struct eap_sm *sm, u16 next_seq_num)
+{
+       struct eap_erp_key *erp;
+       char *home_realm;
+
+       home_realm = eap_home_realm(sm);
+       if (!home_realm || os_strlen(home_realm) == 0) {
+               os_free(home_realm);
+               return -1;
+       }
+
+       erp = eap_erp_get_key(sm, home_realm);
+       if (!erp) {
+               wpa_printf(MSG_DEBUG,
+                          "EAP: Failed to find ERP key for realm: %s",
+                          home_realm);
+               os_free(home_realm);
+               return -1;
+       }
+
+       if ((u32) next_seq_num < erp->next_seq) {
+               /* Sequence number has wrapped around, clear this ERP
+                * info and do a full auth next time.
+                */
+               eap_peer_erp_free_key(erp);
+       } else {
+               erp->next_seq = (u32) next_seq_num;
+       }
+
+       os_free(home_realm);
+       return 0;
+}
+
+
+int eap_peer_get_erp_info(struct eap_sm *sm, struct eap_peer_config *config,
+                         const u8 **username, size_t *username_len,
+                         const u8 **realm, size_t *realm_len,
+                         u16 *erp_next_seq_num, const u8 **rrk,
+                         size_t *rrk_len)
+{
+       struct eap_erp_key *erp;
+       char *home_realm;
+       char *pos;
+
+       home_realm = eap_get_realm(sm, config);
+       if (!home_realm || os_strlen(home_realm) == 0) {
+               os_free(home_realm);
+               return -1;
+       }
+
+       erp = eap_erp_get_key(sm, home_realm);
+       os_free(home_realm);
+       if (!erp)
+               return -1;
+
+       if (erp->next_seq >= 65536)
+               return -1; /* SEQ has range of 0..65535 */
+
+       pos = os_strchr(erp->keyname_nai, '@');
+       *username_len = pos - erp->keyname_nai;
+       *username = (u8 *) erp->keyname_nai;
+
+       pos++;
+       *realm_len = os_strlen(pos);
+       *realm = (u8 *) pos;
+
+       *erp_next_seq_num = (u16) erp->next_seq;
+
+       *rrk_len = erp->rRK_len;
+       *rrk = erp->rRK;
+
+       if (*username_len == 0 || *realm_len == 0 || *rrk_len == 0)
+               return -1;
+
+       return 0;
+}
+
 #endif /* CONFIG_ERP */
 
 
index 932584fb287373a7f37e3006f59bd8ac43164951..883ba242330a595eb96cbbfc6b436be406ae275a 100644 (file)
@@ -358,6 +358,11 @@ int eap_peer_was_failure_expected(struct eap_sm *sm);
 void eap_peer_erp_free_keys(struct eap_sm *sm);
 struct wpabuf * eap_peer_build_erp_reauth_start(struct eap_sm *sm, u8 eap_id);
 void eap_peer_finish(struct eap_sm *sm, const struct eap_hdr *hdr, size_t len);
+int eap_peer_get_erp_info(struct eap_sm *sm, struct eap_peer_config *config,
+                         const u8 **username, size_t *username_len,
+                         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);
 
 #endif /* IEEE8021X_EAPOL */
 
index e72700598a67a85ae75d4a42969a5716e6dfd75a..81761b1895103ef4a409565edf4174f1b761da77 100644 (file)
@@ -2195,3 +2195,33 @@ void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf,
        eap_peer_finish(sm->eap, (const struct eap_hdr *) buf, len);
 #endif /* CONFIG_ERP */
 }
+
+
+int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num)
+{
+#ifdef CONFIG_ERP
+       if (!sm)
+               return -1;
+       return eap_peer_update_erp_next_seq_num(sm->eap, next_seq_num);
+#else /* CONFIG_ERP */
+       return -1;
+#endif /* CONFIG_ERP */
+}
+
+
+int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config,
+                         const u8 **username, size_t *username_len,
+                         const u8 **realm, size_t *realm_len,
+                         u16 *erp_next_seq_num, const u8 **rrk,
+                         size_t *rrk_len)
+{
+#ifdef CONFIG_ERP
+       if (!sm)
+               return -1;
+       return eap_peer_get_erp_info(sm->eap, config, username, username_len,
+                                    realm, realm_len, erp_next_seq_num, rrk,
+                                    rrk_len);
+#else /* CONFIG_ERP */
+       return -1;
+#endif /* CONFIG_ERP */
+}
index cb06e9a07c38f3d7425debca901593de71c7cccb..aa91b8cd545186d0465e4c4bb9ac700425789940 100644 (file)
@@ -340,6 +340,13 @@ struct wpabuf * eapol_sm_build_erp_reauth_start(struct eapol_sm *sm);
 void eapol_sm_process_erp_finish(struct eapol_sm *sm, const u8 *buf,
                                 size_t len);
 int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len);
+int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm, u16 next_seq_num);
+int eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config,
+                         const u8 **username, size_t *username_len,
+                         const u8 **realm, size_t *realm_len,
+                         u16 *erp_next_seq_num, const u8 **rrk,
+                         size_t *rrk_len);
+
 #else /* IEEE8021X_EAPOL */
 static inline struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx)
 {
@@ -458,6 +465,19 @@ static inline void eapol_sm_process_erp_finish(struct eapol_sm *sm,
                                               const u8 *buf, size_t len)
 {
 }
+static inline int eapol_sm_update_erp_next_seq_num(struct eapol_sm *sm,
+                                                  u16 next_seq_num)
+{
+       return -1;
+}
+static inline int
+eapol_sm_get_erp_info(struct eapol_sm *sm, struct eap_peer_config *config,
+                     const u8 **username, size_t *username_len,
+                     const u8 **realm, size_t *realm_len,
+                     u16 *erp_next_seq_num, const u8 **rrk, size_t *rrk_len)
+{
+       return -1;
+}
 #endif /* IEEE8021X_EAPOL */
 
 #endif /* EAPOL_SUPP_SM_H */