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 <jouni@qca.qualcomm.com>
This commit is contained in:
Vidyullatha Kanchanapally 2017-03-22 16:10:05 +05:30 committed by Jouni Malinen
parent 42e69bda2a
commit 15def72fab
4 changed files with 140 additions and 2 deletions

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

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

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

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