From 15def72fabd1116930f5ffdb09983cae1e8021a3 Mon Sep 17 00:00:00 2001 From: Vidyullatha Kanchanapally Date: Wed, 22 Mar 2017 16:10:05 +0530 Subject: [PATCH] ERP: External control of ERP key information 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 --- src/eap_peer/eap.c | 87 +++++++++++++++++++++++++++++++++- src/eap_peer/eap.h | 5 ++ src/eapol_supp/eapol_supp_sm.c | 30 ++++++++++++ src/eapol_supp/eapol_supp_sm.h | 20 ++++++++ 4 files changed, 140 insertions(+), 2 deletions(-) diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c index bc90c7af9..d0f305f1a 100644 --- a/src/eap_peer/eap.c +++ b/src/eap_peer/eap.c @@ -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 */ diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h index 932584fb2..883ba2423 100644 --- a/src/eap_peer/eap.h +++ b/src/eap_peer/eap.h @@ -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 */ diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c index e72700598..81761b189 100644 --- a/src/eapol_supp/eapol_supp_sm.c +++ b/src/eapol_supp/eapol_supp_sm.c @@ -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 */ +} diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h index cb06e9a07..aa91b8cd5 100644 --- a/src/eapol_supp/eapol_supp_sm.h +++ b/src/eapol_supp/eapol_supp_sm.h @@ -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 */