Browse Source

EAP-AKA': Update to RFC 5448

There was a technical change between the last IETF draft version
(draft-arkko-eap-aka-kdf-10) and RFC 5448 in the leading characters
used in the username (i.e., use unique characters for EAP-AKA' instead
of reusing the EAP-AKA ones). This commit updates EAP-AKA' server and
peer implementations to use the leading characters based on the final
RFC.

Note: This will make EAP-AKA' not interoperate between the earlier
draft version and the new version.

Signed-hostap: Jouni Malinen <j@w1.fi>
intended-for: hostap-1
Jouni Malinen 13 years ago
parent
commit
762e4ce620

+ 6 - 0
hostapd/hostapd.eap_user

@@ -69,6 +69,9 @@
 "3"*		SIM,TTLS,TLS,PEAP,AKA
 "4"*		AKA,TTLS,TLS,PEAP,SIM
 "5"*		SIM,TTLS,TLS,PEAP,AKA
+"6"*		AKA'
+"7"*		AKA'
+"8"*		AKA'
 
 # Wildcard for all other identities
 *		PEAP,TTLS,TLS,SIM,AKA
@@ -89,3 +92,6 @@
 "3"*		SIM	[2]
 "4"*		AKA	[2]
 "5"*		SIM	[2]
+"6"*		AKA'	[2]
+"7"*		AKA'	[2]
+"8"*		AKA'	[2]

+ 1 - 1
src/eap_common/eap_defs.h

@@ -60,7 +60,7 @@ typedef enum {
 	EAP_TYPE_PSK = 47 /* RFC 4764 */,
 	EAP_TYPE_SAKE = 48 /* RFC 4763 */,
 	EAP_TYPE_IKEV2 = 49 /* RFC 5106 */,
-	EAP_TYPE_AKA_PRIME = 50 /* draft-arkko-eap-aka-kdf-10.txt */,
+	EAP_TYPE_AKA_PRIME = 50 /* RFC 5448 */,
 	EAP_TYPE_GPSK = 51 /* RFC 5433 */,
 	EAP_TYPE_PWD = 52 /* RFC 5931 */,
 	EAP_TYPE_EXPANDED = 254 /* RFC 3748 */

+ 19 - 3
src/eap_peer/eap.c

@@ -938,7 +938,7 @@ static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi,
 static int eap_sm_imsi_identity(struct eap_sm *sm,
 				struct eap_peer_config *conf)
 {
-	int aka = 0;
+	enum { EAP_SM_SIM, EAP_SM_AKA, EAP_SM_AKA_PRIME } method = EAP_SM_SIM;
 	char imsi[100];
 	size_t imsi_len;
 	struct eap_method_type *m = conf->eap_methods;
@@ -965,9 +965,15 @@ static int eap_sm_imsi_identity(struct eap_sm *sm,
 
 	for (i = 0; m && (m[i].vendor != EAP_VENDOR_IETF ||
 			  m[i].method != EAP_TYPE_NONE); i++) {
+		if (m[i].vendor == EAP_VENDOR_IETF &&
+		    m[i].method == EAP_TYPE_AKA_PRIME) {
+			method = EAP_SM_AKA_PRIME;
+			break;
+		}
+
 		if (m[i].vendor == EAP_VENDOR_IETF &&
 		    m[i].method == EAP_TYPE_AKA) {
-			aka = 1;
+			method = EAP_SM_AKA;
 			break;
 		}
 	}
@@ -980,7 +986,17 @@ static int eap_sm_imsi_identity(struct eap_sm *sm,
 		return -1;
 	}
 
-	conf->identity[0] = aka ? '0' : '1';
+	switch (method) {
+	case EAP_SM_SIM:
+		conf->identity[0] = '1';
+		break;
+	case EAP_SM_AKA:
+		conf->identity[0] = '0';
+		break;
+	case EAP_SM_AKA_PRIME:
+		conf->identity[0] = '6';
+		break;
+	}
 	os_memcpy(conf->identity + 1, imsi, imsi_len);
 	conf->identity_len = 1 + imsi_len;
 

+ 2 - 2
src/eap_peer/eap_aka.c

@@ -1,6 +1,6 @@
 /*
- * EAP peer method: EAP-AKA (RFC 4187) and EAP-AKA' (draft-arkko-eap-aka-kdf)
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * EAP peer method: EAP-AKA (RFC 4187) and EAP-AKA' (RFC 5448)
+ * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.

+ 12 - 5
src/eap_server/eap_server_aka.c

@@ -1,6 +1,6 @@
 /*
- * 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 software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -294,7 +294,10 @@ static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data,
 	os_free(data->next_pseudonym);
 	if (nonce_s == NULL) {
 		data->next_pseudonym =
-			eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 1);
+			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;
@@ -302,7 +305,10 @@ static int eap_aka_build_encr(struct eap_sm *sm, struct eap_aka_data *data,
 	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");
@@ -620,7 +626,8 @@ static void eap_aka_determine_identity(struct eap_sm *sm,
 		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) {
+		   (sm->identity[0] == EAP_AKA_PERMANENT_PREFIX ||
+		    sm->identity[0] == EAP_AKA_PRIME_PERMANENT_PREFIX)) {
 		identity = sm->identity;
 		identity_len = sm->identity_len;
 	} else {

+ 4 - 2
src/eap_server/eap_server_sim.c

@@ -133,7 +133,8 @@ static int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data,
 	os_free(data->next_pseudonym);
 	if (nonce_s == NULL) {
 		data->next_pseudonym =
-			eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv, 0);
+			eap_sim_db_get_next_pseudonym(sm->eap_sim_db_priv,
+						      EAP_SIM_DB_SIM);
 	} else {
 		/* Do not update pseudonym during re-authentication */
 		data->next_pseudonym = NULL;
@@ -141,7 +142,8 @@ static int eap_sim_build_encr(struct eap_sm *sm, struct eap_sim_data *data,
 	os_free(data->next_reauth_id);
 	if (data->counter <= EAP_SIM_MAX_FAST_REAUTHS) {
 		data->next_reauth_id =
-			eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv, 0);
+			eap_sim_db_get_next_reauth_id(sm->eap_sim_db_priv,
+						      EAP_SIM_DB_SIM);
 	} else {
 		wpa_printf(MSG_DEBUG, "EAP-SIM: Max fast re-authentication "
 			   "count exceeded - force full authentication");

+ 55 - 20
src/eap_server/eap_sim_db.c

@@ -1,6 +1,6 @@
 /*
  * hostapd / EAP-SIM database/authenticator gateway
- * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2005-2010, 2012, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -647,7 +647,8 @@ eap_sim_db_get_pseudonym(struct eap_sim_db_data *data, const u8 *identity,
 
 	if (identity_len == 0 ||
 	    (identity[0] != EAP_SIM_PSEUDONYM_PREFIX &&
-	     identity[0] != EAP_AKA_PSEUDONYM_PREFIX))
+	     identity[0] != EAP_AKA_PSEUDONYM_PREFIX &&
+	     identity[0] != EAP_AKA_PRIME_PSEUDONYM_PREFIX))
 		return NULL;
 
 	/* Remove possible realm from identity */
@@ -685,7 +686,8 @@ eap_sim_db_get_pseudonym_id(struct eap_sim_db_data *data, const u8 *identity,
 
 	if (identity_len == 0 ||
 	    (identity[0] != EAP_SIM_PERMANENT_PREFIX &&
-	     identity[0] != EAP_AKA_PERMANENT_PREFIX))
+	     identity[0] != EAP_AKA_PERMANENT_PREFIX &&
+	     identity[0] != EAP_AKA_PRIME_PERMANENT_PREFIX))
 		return NULL;
 
 	p = data->pseudonyms;
@@ -710,7 +712,8 @@ eap_sim_db_get_reauth(struct eap_sim_db_data *data, const u8 *identity,
 
 	if (identity_len == 0 ||
 	    (identity[0] != EAP_SIM_REAUTH_ID_PREFIX &&
-	     identity[0] != EAP_AKA_REAUTH_ID_PREFIX))
+	     identity[0] != EAP_AKA_REAUTH_ID_PREFIX &&
+	     identity[0] != EAP_AKA_PRIME_REAUTH_ID_PREFIX))
 		return NULL;
 
 	/* Remove possible realm from identity */
@@ -777,8 +780,9 @@ eap_sim_db_get_reauth_id(struct eap_sim_db_data *data, const u8 *identity,
  * @identity_len: Length of identity in bytes 
  * Returns: 0 if the user is found or -1 on failure
  *
- * In most cases, the user name is ['0','1'] | IMSI, i.e., 1 followed by the
- * IMSI in ASCII format, ['2','3'] | pseudonym, or ['4','5'] | reauth_id.
+ * In most cases, the user name is ['0','1','6'] | IMSI, i.e., 1 followed by
+ * the IMSI in ASCII format for EAP-SIM, ['2','3','7'] | pseudonym, or
+ * ['4','5','7'] | reauth_id.
  */
 int eap_sim_db_identity_known(void *priv, const u8 *identity,
 			      size_t identity_len)
@@ -789,21 +793,24 @@ int eap_sim_db_identity_known(void *priv, const u8 *identity,
 		return -1;
 
 	if (identity[0] == EAP_SIM_PSEUDONYM_PREFIX ||
-	    identity[0] == EAP_AKA_PSEUDONYM_PREFIX) {
+	    identity[0] == EAP_AKA_PSEUDONYM_PREFIX ||
+	    identity[0] == EAP_AKA_PRIME_PSEUDONYM_PREFIX) {
 		struct eap_sim_pseudonym *p =
 			eap_sim_db_get_pseudonym(data, identity, identity_len);
 		return p ? 0 : -1;
 	}
 
 	if (identity[0] == EAP_SIM_REAUTH_ID_PREFIX ||
-	    identity[0] == EAP_AKA_REAUTH_ID_PREFIX) {
+	    identity[0] == EAP_AKA_REAUTH_ID_PREFIX ||
+	    identity[0] == EAP_AKA_PRIME_REAUTH_ID_PREFIX) {
 		struct eap_sim_reauth *r =
 			eap_sim_db_get_reauth(data, identity, identity_len);
 		return r ? 0 : -1;
 	}
 
 	if (identity[0] != EAP_SIM_PERMANENT_PREFIX &&
-	    identity[0] != EAP_AKA_PERMANENT_PREFIX) {
+	    identity[0] != EAP_AKA_PERMANENT_PREFIX &&
+	    identity[0] != EAP_AKA_PRIME_PERMANENT_PREFIX) {
 		/* Unknown identity prefix */
 		return -1;
 	}
@@ -843,7 +850,7 @@ static char * eap_sim_db_get_next(struct eap_sim_db_data *data, char prefix)
 /**
  * eap_sim_db_get_next_pseudonym - EAP-SIM DB: Get next pseudonym
  * @priv: Private data pointer from eap_sim_db_init()
- * @aka: Using EAP-AKA instead of EAP-SIM
+ * @method: EAP method (SIM/AKA/AKA')
  * Returns: Next pseudonym (allocated string) or %NULL on failure
  *
  * This function is used to generate a pseudonym for EAP-SIM. The returned
@@ -851,18 +858,31 @@ static char * eap_sim_db_get_next(struct eap_sim_db_data *data, char prefix)
  * with eap_sim_db_add_pseudonym() once the authentication has been completed
  * successfully. Caller is responsible for freeing the returned buffer.
  */
-char * eap_sim_db_get_next_pseudonym(void *priv, int aka)
+char * eap_sim_db_get_next_pseudonym(void *priv, enum eap_sim_db_method method)
 {
 	struct eap_sim_db_data *data = priv;
-	return eap_sim_db_get_next(data, aka ? EAP_AKA_PSEUDONYM_PREFIX :
-				   EAP_SIM_PSEUDONYM_PREFIX);
+	char prefix = EAP_SIM_REAUTH_ID_PREFIX;
+
+	switch (method) {
+	case EAP_SIM_DB_SIM:
+		prefix = EAP_SIM_PSEUDONYM_PREFIX;
+		break;
+	case EAP_SIM_DB_AKA:
+		prefix = EAP_AKA_PSEUDONYM_PREFIX;
+		break;
+	case EAP_SIM_DB_AKA_PRIME:
+		prefix = EAP_AKA_PRIME_PSEUDONYM_PREFIX;
+		break;
+	}
+
+	return eap_sim_db_get_next(data, prefix);
 }
 
 
 /**
  * eap_sim_db_get_next_reauth_id - EAP-SIM DB: Get next reauth_id
  * @priv: Private data pointer from eap_sim_db_init()
- * @aka: Using EAP-AKA instead of EAP-SIM
+ * @method: EAP method (SIM/AKA/AKA')
  * Returns: Next reauth_id (allocated string) or %NULL on failure
  *
  * This function is used to generate a fast re-authentication identity for
@@ -871,11 +891,24 @@ char * eap_sim_db_get_next_pseudonym(void *priv, int aka)
  * has been completed successfully. Caller is responsible for freeing the
  * returned buffer.
  */
-char * eap_sim_db_get_next_reauth_id(void *priv, int aka)
+char * eap_sim_db_get_next_reauth_id(void *priv, enum eap_sim_db_method method)
 {
 	struct eap_sim_db_data *data = priv;
-	return eap_sim_db_get_next(data, aka ? EAP_AKA_REAUTH_ID_PREFIX :
-				   EAP_SIM_REAUTH_ID_PREFIX);
+	char prefix = EAP_SIM_REAUTH_ID_PREFIX;
+
+	switch (method) {
+	case EAP_SIM_DB_SIM:
+		prefix = EAP_SIM_REAUTH_ID_PREFIX;
+		break;
+	case EAP_SIM_DB_AKA:
+		prefix = EAP_AKA_REAUTH_ID_PREFIX;
+		break;
+	case EAP_SIM_DB_AKA_PRIME:
+		prefix = EAP_AKA_PRIME_REAUTH_ID_PREFIX;
+		break;
+	}
+
+	return eap_sim_db_get_next(data, prefix);
 }
 
 
@@ -1156,7 +1189,7 @@ void eap_sim_db_remove_reauth(void *priv, struct eap_sim_reauth *reauth)
  * called once the results become available.
  *
  * In most cases, the user name is '0' | IMSI, i.e., 0 followed by the IMSI in
- * ASCII format.
+ * ASCII format for EAP-AKA and '6' | IMSI for EAP-AKA'.
  *
  * When using an external server for AKA authentication, this function can
  * always start a request and return EAP_SIM_DB_PENDING immediately if
@@ -1178,7 +1211,8 @@ int eap_sim_db_get_aka_auth(void *priv, const u8 *identity,
 	char msg[40];
 
 	if (identity_len < 2 || identity == NULL ||
-	    identity[0] != EAP_AKA_PERMANENT_PREFIX) {
+	    (identity[0] != EAP_AKA_PERMANENT_PREFIX &&
+	     identity[0] != EAP_AKA_PRIME_PERMANENT_PREFIX)) {
 		wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity",
 				  identity, identity_len);
 		return EAP_SIM_DB_FAILURE;
@@ -1281,7 +1315,8 @@ int eap_sim_db_resynchronize(void *priv, const u8 *identity,
 	size_t i;
 
 	if (identity_len < 2 || identity == NULL ||
-	    identity[0] != EAP_AKA_PERMANENT_PREFIX) {
+	    (identity[0] != EAP_AKA_PERMANENT_PREFIX &&
+	     identity[0] != EAP_AKA_PRIME_PERMANENT_PREFIX)) {
 		wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity",
 				  identity, identity_len);
 		return -1;

+ 14 - 3
src/eap_server/eap_sim_db.h

@@ -1,6 +1,6 @@
 /*
  * hostapd / EAP-SIM database/authenticator gateway
- * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2005-2008, 2012, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
@@ -18,6 +18,15 @@
 #define EAP_AKA_PERMANENT_PREFIX '0'
 #define EAP_AKA_PSEUDONYM_PREFIX '2'
 #define EAP_AKA_REAUTH_ID_PREFIX '4'
+#define EAP_AKA_PRIME_PERMANENT_PREFIX '6'
+#define EAP_AKA_PRIME_PSEUDONYM_PREFIX '7'
+#define EAP_AKA_PRIME_REAUTH_ID_PREFIX '8'
+
+enum eap_sim_db_method {
+	EAP_SIM_DB_SIM,
+	EAP_SIM_DB_AKA,
+	EAP_SIM_DB_AKA_PRIME
+};
 
 void * eap_sim_db_init(const char *config,
 		       void (*get_complete_cb)(void *ctx, void *session_ctx),
@@ -36,9 +45,11 @@ int eap_sim_db_get_gsm_triplets(void *priv, const u8 *identity,
 int eap_sim_db_identity_known(void *priv, const u8 *identity,
 			      size_t identity_len);
 
-char * eap_sim_db_get_next_pseudonym(void *priv, int aka);
+char * eap_sim_db_get_next_pseudonym(void *priv,
+				     enum eap_sim_db_method method);
 
-char * eap_sim_db_get_next_reauth_id(void *priv, int aka);
+char * eap_sim_db_get_next_reauth_id(void *priv,
+				     enum eap_sim_db_method method);
 
 int eap_sim_db_add_pseudonym(void *priv, const u8 *identity,
 			     size_t identity_len, char *pseudonym);