From 31a3de8af3272f97e7e8b7e7cb2e7c976e6d24b0 Mon Sep 17 00:00:00 2001
From: Jouni Malinen <j@w1.fi>
Date: Sun, 2 Sep 2012 00:38:39 +0300
Subject: [PATCH] EAP-SIM server: Add support for AT_COUNTER_TOO_SMALL

If the peer rejects re-authentication with AT_COUNTER_TOO_SMALL, fall
back to full authentication to allow the authentication session to be
completed.

Signed-hostap: Jouni Malinen <j@w1.fi>
---
 src/eap_server/eap_server_sim.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/src/eap_server/eap_server_sim.c b/src/eap_server/eap_server_sim.c
index d67457bbf..c64b664f4 100644
--- a/src/eap_server/eap_server_sim.c
+++ b/src/eap_server/eap_server_sim.c
@@ -118,6 +118,13 @@ static struct wpabuf * eap_sim_build_start(struct eap_sm *sm,
 	} else if (data->start_round > 3) {
 		/* Cannot use more than three rounds of Start messages */
 		return NULL;
+	} else if (data->start_round == 0) {
+		/*
+		 * This is a special case that is used to recover from
+		 * AT_COUNTER_TOO_SMALL during re-authentication. Since we
+		 * already know the identity of the peer, there is no need to
+		 * request any identity in this case.
+		 */
 	} else if (sm->identity && sm->identity_len > 0 &&
 		   sm->identity[0] == EAP_SIM_REAUTH_ID_PREFIX) {
 		/* Reauth id may have expired - try fullauth */
@@ -410,6 +417,14 @@ static void eap_sim_process_start(struct eap_sm *sm,
 
 	wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response");
 
+	if (data->start_round == 0) {
+		/*
+		 * Special case for AT_COUNTER_TOO_SMALL recovery - no identity
+		 * was requested since we already know it.
+		 */
+		goto skip_id_update;
+	}
+
 	/*
 	 * We always request identity in SIM/Start, so the peer is required to
 	 * have replied with one.
@@ -488,6 +503,7 @@ static void eap_sim_process_start(struct eap_sm *sm,
 		return;
 	}
 
+skip_id_update:
 	/* Full authentication */
 
 	if (attr->nonce_mt == NULL || attr->selected_version < 0) {
@@ -624,6 +640,16 @@ static void eap_sim_process_reauth(struct eap_sm *sm,
 
 	wpa_printf(MSG_DEBUG, "EAP-SIM: Re-authentication response includes "
 		   "the correct AT_MAC");
+
+	if (eattr.counter_too_small) {
+		wpa_printf(MSG_DEBUG, "EAP-AKA: Re-authentication response "
+			   "included AT_COUNTER_TOO_SMALL - starting full "
+			   "authentication");
+		data->start_round = -1;
+		eap_sim_state(data, START);
+		return;
+	}
+
 	if (sm->eap_sim_aka_result_ind && attr->result_ind) {
 		data->use_result_ind = 1;
 		data->notification = EAP_SIM_SUCCESS;