/*
- * hostapd / EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf)
- * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi>
+ * hostapd / EAP-AKA (RFC 4187) and EAP-AKA' (RFC 5448)
+ * Copyright (c) 2005-2012, Jouni Malinen <j@w1.fi>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
*/
#include "includes.h"
#include "common.h"
#include "crypto/sha256.h"
#include "crypto/crypto.h"
+#include "crypto/random.h"
#include "eap_common/eap_sim_common.h"
#include "eap_server/eap_i.h"
#include "eap_server/eap_sim_db.h"
u8 *network_name;
size_t network_name_len;
u16 kdf;
+ int identity_round;
+ char permanent[20]; /* Permanent username */
};
-static void eap_aka_determine_identity(struct eap_sm *sm,
- struct eap_aka_data *data,
- int before_identity, int after_reauth);
+static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data);
static const char * eap_aka_state_txt(int state)
}
+static int eap_aka_check_identity_reauth(struct eap_sm *sm,
+ struct eap_aka_data *data,
+ const char *username)
+{
+ if (data->eap_method == EAP_TYPE_AKA_PRIME &&
+ username[0] != EAP_AKA_PRIME_REAUTH_ID_PREFIX)
+ return 0;
+ if (data->eap_method == EAP_TYPE_AKA &&
+ username[0] != EAP_AKA_REAUTH_ID_PREFIX)
+ return 0;
+
+ wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth username '%s'", username);
+ data->reauth = eap_sim_db_get_reauth_entry(sm->eap_sim_db_priv,
+ username);
+ if (data->reauth == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown reauth identity - "
+ "request full auth identity");
+ /* Remain in IDENTITY state for another round */
+ return 0;
+ }
+
+ wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast re-authentication");
+ os_strlcpy(data->permanent, data->reauth->permanent,
+ sizeof(data->permanent));
+ data->counter = data->reauth->counter;
+ if (data->eap_method == EAP_TYPE_AKA_PRIME) {
+ os_memcpy(data->k_encr, data->reauth->k_encr,
+ EAP_SIM_K_ENCR_LEN);
+ os_memcpy(data->k_aut, data->reauth->k_aut,
+ EAP_AKA_PRIME_K_AUT_LEN);
+ os_memcpy(data->k_re, data->reauth->k_re,
+ EAP_AKA_PRIME_K_RE_LEN);
+ } else {
+ os_memcpy(data->mk, data->reauth->mk, EAP_SIM_MK_LEN);
+ }
+
+ eap_aka_state(data, REAUTH);
+ return 1;
+}
+
+
+static void eap_aka_check_identity(struct eap_sm *sm,
+ struct eap_aka_data *data)
+{
+ char *username;
+
+ /* Check if we already know the identity from EAP-Response/Identity */
+
+ username = sim_get_username(sm->identity, sm->identity_len);
+ if (username == NULL)
+ return;
+
+ if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
+ os_free(username);
+ /*
+ * Since re-auth username was recognized, skip AKA/Identity
+ * exchange.
+ */
+ return;
+ }
+
+ if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
+ username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
+ (data->eap_method == EAP_TYPE_AKA &&
+ username[0] == EAP_AKA_PSEUDONYM_PREFIX)) {
+ const char *permanent;
+ wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
+ username);
+ permanent = eap_sim_db_get_permanent(
+ sm->eap_sim_db_priv, username);
+ if (permanent == NULL) {
+ os_free(username);
+ wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
+ "identity - request permanent identity");
+ /* Remain in IDENTITY state for another round */
+ return;
+ }
+ os_strlcpy(data->permanent, permanent,
+ sizeof(data->permanent));
+ /*
+ * Since pseudonym username was recognized, skip AKA/Identity
+ * exchange.
+ */
+ eap_aka_fullauth(sm, data);
+ }
+
+ os_free(username);
+}
+
+
static void * eap_aka_init(struct eap_sm *sm)
{
struct eap_aka_data *data;
data->eap_method = EAP_TYPE_AKA;
data->state = IDENTITY;
- eap_aka_determine_identity(sm, data, 1, 0);
data->pending_id = -1;
+ eap_aka_check_identity(sm, data);
return data;
}
return NULL;
data->eap_method = EAP_TYPE_AKA_PRIME;
- data->network_name = os_malloc(os_strlen(network_name));
+ data->network_name = (u8 *) os_strdup(network_name);
if (data->network_name == NULL) {
os_free(data);
return NULL;
}
data->network_name_len = os_strlen(network_name);
- os_memcpy(data->network_name, network_name, data->network_name_len);
data->state = IDENTITY;
- eap_aka_determine_identity(sm, data, 1, 0);
data->pending_id = -1;
+ eap_aka_check_identity(sm, data);
return data;
}
os_free(data->next_reauth_id);
wpabuf_free(data->id_msgs);
os_free(data->network_name);
- os_free(data);
+ bin_clear_free(data, sizeof(*data));
}
else
sha1_vector(1, &addr, &len, hash);
- if (os_memcmp(hash, checkcode, hash_len) != 0) {
+ if (os_memcmp_const(hash, checkcode, hash_len) != 0) {
wpa_printf(MSG_DEBUG, "EAP-AKA: Mismatch in AT_CHECKCODE");
return -1;
}
wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Identity");
msg = eap_sim_msg_init(EAP_CODE_REQUEST, id, data->eap_method,
EAP_AKA_SUBTYPE_IDENTITY);
- if (eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity,
- sm->identity_len)) {
- wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ");
- eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
- } else {
+ data->identity_round++;
+ if (data->identity_round == 1) {
/*
* RFC 4187, Chap. 4.1.4 recommends that identity from EAP is
* ignored and the AKA/Identity is used to request the
*/
wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ");
eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0);
+ } else if (data->identity_round > 3) {
+ /* Cannot use more than three rounds of Identity messages */
+ eap_sim_msg_free(msg);
+ return NULL;
+ } else if (sm->identity && sm->identity_len > 0 &&
+ (sm->identity[0] == EAP_AKA_REAUTH_ID_PREFIX ||
+ sm->identity[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX)) {
+ /* Reauth id may have expired - try fullauth */
+ wpa_printf(MSG_DEBUG, " AT_FULLAUTH_ID_REQ");
+ eap_sim_msg_add(msg, EAP_SIM_AT_FULLAUTH_ID_REQ, 0, NULL, 0);
+ } else {
+ wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ");
+ eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0);
}
- buf = eap_sim_msg_finish(msg, NULL, NULL, 0);
+ buf = eap_sim_msg_finish(msg, data->eap_method, NULL, NULL, 0);
if (eap_aka_add_id_msg(data, buf) < 0) {
wpabuf_free(buf);
return NULL;
const u8 *nonce_s)
{
os_free(data->next_pseudonym);
- data->next_pseudonym =
- eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 1);
+ if (nonce_s == NULL) {
+ data->next_pseudonym =
+ eap_sim_db_get_next_pseudonym(
+ sm->eap_sim_db_priv,
+ data->eap_method == EAP_TYPE_AKA_PRIME ?
+ EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
+ } else {
+ /* Do not update pseudonym during re-authentication */
+ data->next_pseudonym = NULL;
+ }
os_free(data->next_reauth_id);
if (data->counter <= EAP_AKA_MAX_FAST_REAUTHS) {
data->next_reauth_id =
- eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 1);
+ eap_sim_db_get_next_reauth_id(
+ sm->eap_sim_db_priv,
+ data->eap_method == EAP_TYPE_AKA_PRIME ?
+ EAP_SIM_DB_AKA_PRIME : EAP_SIM_DB_AKA);
} else {
wpa_printf(MSG_DEBUG, "EAP-AKA: Max fast re-authentication "
"count exceeded - force full authentication");
wpa_printf(MSG_DEBUG, " AT_MAC");
eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
- return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
+ return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0);
}
wpa_printf(MSG_DEBUG, "EAP-AKA: Generating Re-authentication");
- if (os_get_random(data->nonce_s, EAP_SIM_NONCE_S_LEN))
+ if (random_get_bytes(data->nonce_s, EAP_SIM_NONCE_S_LEN))
return NULL;
wpa_hexdump_key(MSG_MSGDUMP, "EAP-AKA: NONCE_S",
data->nonce_s, EAP_SIM_NONCE_S_LEN);
wpa_printf(MSG_DEBUG, " AT_MAC");
eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
- return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
+ return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0);
}
wpa_printf(MSG_DEBUG, " AT_MAC");
eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC);
}
- return eap_sim_msg_finish(msg, data->k_aut, NULL, 0);
+ return eap_sim_msg_finish(msg, data->eap_method, data->k_aut, NULL, 0);
}
static void eap_aka_determine_identity(struct eap_sm *sm,
- struct eap_aka_data *data,
- int before_identity, int after_reauth)
+ struct eap_aka_data *data)
{
- const u8 *identity;
- size_t identity_len;
- int res;
+ char *username;
- identity = NULL;
- identity_len = 0;
+ wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity",
+ sm->identity, sm->identity_len);
- if (after_reauth && data->reauth) {
- identity = data->reauth->identity;
- identity_len = data->reauth->identity_len;
- } else if (sm->identity && sm->identity_len > 0 &&
- sm->identity[0] == EAP_AKA_PERMANENT_PREFIX) {
- identity = sm->identity;
- identity_len = sm->identity_len;
- } else {
- identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv,
- sm->identity,
- sm->identity_len,
- &identity_len);
- if (identity == NULL) {
- data->reauth = eap_sim_db_get_reauth_entry(
- sm->eap_sim_db_priv, sm->identity,
- sm->identity_len);
- if (data->reauth &&
- data->reauth->aka_prime !=
- (data->eap_method == EAP_TYPE_AKA_PRIME)) {
- wpa_printf(MSG_DEBUG, "EAP-AKA: Reauth data "
- "was for different AKA version");
- data->reauth = NULL;
- }
- if (data->reauth) {
- wpa_printf(MSG_DEBUG, "EAP-AKA: Using fast "
- "re-authentication");
- identity = data->reauth->identity;
- identity_len = data->reauth->identity_len;
- data->counter = data->reauth->counter;
- if (data->eap_method == EAP_TYPE_AKA_PRIME) {
- os_memcpy(data->k_encr,
- data->reauth->k_encr,
- EAP_SIM_K_ENCR_LEN);
- os_memcpy(data->k_aut,
- data->reauth->k_aut,
- EAP_AKA_PRIME_K_AUT_LEN);
- os_memcpy(data->k_re,
- data->reauth->k_re,
- EAP_AKA_PRIME_K_RE_LEN);
- } else {
- os_memcpy(data->mk, data->reauth->mk,
- EAP_SIM_MK_LEN);
- }
- }
- }
+ username = sim_get_username(sm->identity, sm->identity_len);
+ if (username == NULL) {
+ data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
+ eap_aka_state(data, NOTIFICATION);
+ return;
}
- if (identity == NULL ||
- eap_sim_db_identity_known(sm->eap_sim_db_priv, sm->identity,
- sm->identity_len) < 0) {
- if (before_identity) {
- wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent user name "
- "not known - send AKA-Identity request");
- eap_aka_state(data, IDENTITY);
- return;
- } else {
- wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown whether the "
- "permanent user name is known; try to use "
- "it");
- /* eap_sim_db_get_aka_auth() will report failure, if
- * this identity is not known. */
- }
+ if (eap_aka_check_identity_reauth(sm, data, username) > 0) {
+ os_free(username);
+ return;
}
- wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity",
- identity, identity_len);
+ if (((data->eap_method == EAP_TYPE_AKA_PRIME &&
+ username[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX) ||
+ (data->eap_method == EAP_TYPE_AKA &&
+ username[0] == EAP_AKA_REAUTH_ID_PREFIX)) &&
+ data->identity_round == 1) {
+ /* Remain in IDENTITY state for another round to request full
+ * auth identity since we did not recognize reauth id */
+ os_free(username);
+ return;
+ }
- if (!after_reauth && data->reauth) {
- eap_aka_state(data, REAUTH);
+ if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
+ username[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) ||
+ (data->eap_method == EAP_TYPE_AKA &&
+ username[0] == EAP_AKA_PSEUDONYM_PREFIX)) {
+ const char *permanent;
+ wpa_printf(MSG_DEBUG, "EAP-AKA: Pseudonym username '%s'",
+ username);
+ permanent = eap_sim_db_get_permanent(
+ sm->eap_sim_db_priv, username);
+ os_free(username);
+ if (permanent == NULL) {
+ wpa_printf(MSG_DEBUG, "EAP-AKA: Unknown pseudonym "
+ "identity - request permanent identity");
+ /* Remain in IDENTITY state for another round */
+ return;
+ }
+ os_strlcpy(data->permanent, permanent,
+ sizeof(data->permanent));
+ } else if ((data->eap_method == EAP_TYPE_AKA_PRIME &&
+ username[0] == EAP_AKA_PRIME_PERMANENT_PREFIX) ||
+ (data->eap_method == EAP_TYPE_AKA &&
+ username[0] == EAP_AKA_PERMANENT_PREFIX)) {
+ wpa_printf(MSG_DEBUG, "EAP-AKA: Permanent username '%s'",
+ username);
+ os_strlcpy(data->permanent, username, sizeof(data->permanent));
+ os_free(username);
+ } else {
+ wpa_printf(MSG_DEBUG, "EAP-AKA: Unrecognized username '%s'",
+ username);
+ os_free(username);
+ data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
+ eap_aka_state(data, NOTIFICATION);
return;
}
- res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, identity,
- identity_len, data->rand, data->autn,
- data->ik, data->ck, data->res,
- &data->res_len, sm);
+ eap_aka_fullauth(sm, data);
+}
+
+
+static void eap_aka_fullauth(struct eap_sm *sm, struct eap_aka_data *data)
+{
+ size_t identity_len;
+ int res;
+
+ res = eap_sim_db_get_aka_auth(sm->eap_sim_db_priv, data->permanent,
+ data->rand, data->autn, data->ik,
+ data->ck, data->res, &data->res_len, sm);
if (res == EAP_SIM_DB_PENDING) {
wpa_printf(MSG_DEBUG, "EAP-AKA: AKA authentication data "
"not yet available - pending request");
sm->identity, identity_len);
if (data->eap_method == EAP_TYPE_AKA_PRIME) {
- eap_aka_prime_derive_keys(identity, identity_len, data->ik,
+ eap_aka_prime_derive_keys(sm->identity, identity_len, data->ik,
data->ck, data->k_encr, data->k_aut,
data->k_re, data->msk, data->emsk);
} else {
struct wpabuf *respData,
struct eap_sim_attrs *attr)
{
+ u8 *new_identity;
+
wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Identity");
if (attr->mac || attr->iv || attr->encr_data) {
return;
}
- if (attr->identity) {
- os_free(sm->identity);
- sm->identity = os_malloc(attr->identity_len);
- if (sm->identity) {
- os_memcpy(sm->identity, attr->identity,
- attr->identity_len);
- sm->identity_len = attr->identity_len;
- }
+ /*
+ * We always request identity with AKA/Identity, so the peer is
+ * required to have replied with one.
+ */
+ if (!attr->identity || attr->identity_len == 0) {
+ wpa_printf(MSG_DEBUG, "EAP-AKA: Peer did not provide any "
+ "identity");
+ data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
+ eap_aka_state(data, NOTIFICATION);
+ return;
}
- eap_aka_determine_identity(sm, data, 0, 0);
+ new_identity = os_malloc(attr->identity_len);
+ if (new_identity == NULL) {
+ data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
+ eap_aka_state(data, NOTIFICATION);
+ return;
+ }
+ os_free(sm->identity);
+ sm->identity = new_identity;
+ os_memcpy(sm->identity, attr->identity, attr->identity_len);
+ sm->identity_len = attr->identity_len;
+
+ eap_aka_determine_identity(sm, data);
if (eap_get_id(respData) == data->pending_id) {
data->pending_id = -1;
eap_aka_add_id_msg(data, respData);
struct wpabuf *respData,
struct eap_sim_attrs *attr)
{
- const u8 *identity;
- size_t identity_len;
-
wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Challenge");
#ifdef EAP_SERVER_AKA_PRIME
*/
if (attr->res == NULL || attr->res_len < data->res_len ||
attr->res_len_bits != data->res_len * 8 ||
- os_memcmp(attr->res, data->res, data->res_len) != 0) {
+ os_memcmp_const(attr->res, data->res, data->res_len) != 0) {
wpa_printf(MSG_WARNING, "EAP-AKA: Challenge message did not "
"include valid AT_RES (attr len=%lu, res len=%lu "
"bits, expected %lu bits)",
} else
eap_aka_state(data, SUCCESS);
- identity = eap_sim_db_get_permanent(sm->eap_sim_db_priv, sm->identity,
- sm->identity_len, &identity_len);
- if (identity == NULL) {
- identity = sm->identity;
- identity_len = sm->identity_len;
- }
-
if (data->next_pseudonym) {
- eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
- identity_len,
+ eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, data->permanent,
data->next_pseudonym);
data->next_pseudonym = NULL;
}
if (data->eap_method == EAP_TYPE_AKA_PRIME) {
#ifdef EAP_SERVER_AKA_PRIME
eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
- identity,
- identity_len,
+ data->permanent,
data->next_reauth_id,
data->counter + 1,
data->k_encr, data->k_aut,
data->k_re);
#endif /* EAP_SERVER_AKA_PRIME */
} else {
- eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
- identity_len,
+ eap_sim_db_add_reauth(sm->eap_sim_db_priv,
+ data->permanent,
data->next_reauth_id,
data->counter + 1,
data->mk);
* maintaining a local flag stating whether this AUTS has already been
* reported. */
if (!data->auts_reported &&
- eap_sim_db_resynchronize(sm->eap_sim_db_priv, sm->identity,
- sm->identity_len, attr->auts,
- data->rand)) {
+ eap_sim_db_resynchronize(sm->eap_sim_db_priv, data->permanent,
+ attr->auts, data->rand)) {
wpa_printf(MSG_WARNING, "EAP-AKA: Resynchronization failed");
data->notification = EAP_SIM_GENERAL_FAILURE_BEFORE_AUTH;
eap_aka_state(data, NOTIFICATION);
}
data->auts_reported = 1;
- /* Try again after resynchronization */
- eap_aka_determine_identity(sm, data, 0, 0);
+ /* Remain in CHALLENGE state to re-try after resynchronization */
+ eap_aka_fullauth(sm, data);
}
{
struct eap_sim_attrs eattr;
u8 *decrypted = NULL;
- const u8 *identity, *id2;
- size_t identity_len, id2_len;
wpa_printf(MSG_DEBUG, "EAP-AKA: Processing Reauthentication");
wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response "
"included AT_COUNTER_TOO_SMALL - starting full "
"authentication");
- eap_aka_determine_identity(sm, data, 0, 1);
+ eap_aka_fullauth(sm, data);
return;
}
} else
eap_aka_state(data, SUCCESS);
- if (data->reauth) {
- identity = data->reauth->identity;
- identity_len = data->reauth->identity_len;
- } else {
- identity = sm->identity;
- identity_len = sm->identity_len;
- }
-
- id2 = eap_sim_db_get_permanent(sm->eap_sim_db_priv, identity,
- identity_len, &id2_len);
- if (id2) {
- identity = id2;
- identity_len = id2_len;
- }
-
- if (data->next_pseudonym) {
- eap_sim_db_add_pseudonym(sm->eap_sim_db_priv, identity,
- identity_len, data->next_pseudonym);
- data->next_pseudonym = NULL;
- }
if (data->next_reauth_id) {
if (data->eap_method == EAP_TYPE_AKA_PRIME) {
#ifdef EAP_SERVER_AKA_PRIME
eap_sim_db_add_reauth_prime(sm->eap_sim_db_priv,
- identity,
- identity_len,
+ data->permanent,
data->next_reauth_id,
data->counter + 1,
data->k_encr, data->k_aut,
data->k_re);
#endif /* EAP_SERVER_AKA_PRIME */
} else {
- eap_sim_db_add_reauth(sm->eap_sim_db_priv, identity,
- identity_len,
+ eap_sim_db_add_reauth(sm->eap_sim_db_priv,
+ data->permanent,
data->next_reauth_id,
data->counter + 1,
data->mk);
}
+static u8 * eap_aka_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_aka_data *data = priv;
+ u8 *id;
+
+ if (data->state != SUCCESS)
+ return NULL;
+
+ *len = 1 + EAP_AKA_RAND_LEN + EAP_AKA_AUTN_LEN;
+ id = os_malloc(*len);
+ if (id == NULL)
+ return NULL;
+
+ id[0] = data->eap_method;
+ os_memcpy(id + 1, data->rand, EAP_AKA_RAND_LEN);
+ os_memcpy(id + 1 + EAP_AKA_RAND_LEN, data->autn, EAP_AKA_AUTN_LEN);
+ wpa_hexdump(MSG_DEBUG, "EAP-AKA: Derived Session-Id", id, *len);
+
+ return id;
+}
+
+
int eap_server_aka_register(void)
{
struct eap_method *eap;
eap->getKey = eap_aka_getKey;
eap->isSuccess = eap_aka_isSuccess;
eap->get_emsk = eap_aka_get_emsk;
+ eap->getSessionId = eap_aka_get_session_id;
ret = eap_server_method_register(eap);
if (ret)
eap->getKey = eap_aka_getKey;
eap->isSuccess = eap_aka_isSuccess;
eap->get_emsk = eap_aka_get_emsk;
+ eap->getSessionId = eap_aka_get_session_id;
ret = eap_server_method_register(eap);
if (ret)