From 681278246232029c334117bd6dc7e74c6b179f96 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 3 Apr 2015 12:44:03 +0300 Subject: [PATCH] hlr_auc_gw: Allow Milenage RES length to be reduced Some USIM use shorter RES length than the 64-bit default from Milenage. Such cases did not interoperate with the hlr_auc_gw implementation. Make it possible to configure the RES length 4..8 octets, i.e., 32 to 64 bits) to support such USIM. Signed-off-by: Jouni Malinen --- hostapd/hlr_auc_gw.c | 32 +++++++++++++++++++++++++++----- hostapd/hlr_auc_gw.milenage_db | 4 +++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/hostapd/hlr_auc_gw.c b/hostapd/hlr_auc_gw.c index 42d59dba7..8afe45701 100644 --- a/hostapd/hlr_auc_gw.c +++ b/hostapd/hlr_auc_gw.c @@ -87,6 +87,7 @@ struct milenage_parameters { u8 amf[2]; u8 sqn[6]; int set; + size_t res_len; }; static struct milenage_parameters *milenage_db = NULL; @@ -96,6 +97,7 @@ static struct milenage_parameters *milenage_db = NULL; #define EAP_AKA_RAND_LEN 16 #define EAP_AKA_AUTN_LEN 16 #define EAP_AKA_AUTS_LEN 14 +#define EAP_AKA_RES_MIN_LEN 4 #define EAP_AKA_RES_MAX_LEN 16 #define EAP_AKA_IK_LEN 16 #define EAP_AKA_CK_LEN 16 @@ -124,7 +126,8 @@ static int db_table_create_milenage(sqlite3 *db) " ki CHAR(32) NOT NULL," " opc CHAR(32) NOT NULL," " amf CHAR(4) NOT NULL," - " sqn CHAR(12) NOT NULL" + " sqn CHAR(12) NOT NULL," + " res_len INTEGER" ");"; printf("Adding database table for milenage information\n"); @@ -190,6 +193,10 @@ static int get_milenage_cb(void *ctx, int argc, char *argv[], char *col[]) printf("Invalid sqn value in database\n"); return -1; } + + if (os_strcmp(col[i], "res_len") == 0 && argv[i]) { + m->res_len = atoi(argv[i]); + } } return 0; @@ -206,8 +213,7 @@ static struct milenage_parameters * db_get_milenage(const char *imsi_txt) os_snprintf(db_tmp_milenage.imsi, sizeof(db_tmp_milenage.imsi), "%llu", imsi); os_snprintf(cmd, sizeof(cmd), - "SELECT ki,opc,amf,sqn FROM milenage WHERE imsi=%llu;", - imsi); + "SELECT * FROM milenage WHERE imsi=%llu;", imsi); if (sqlite3_exec(sqlite_db, cmd, get_milenage_cb, &db_tmp_milenage, NULL) != SQLITE_OK) return NULL; @@ -424,7 +430,7 @@ static int read_milenage(const char *fname) while (fgets(buf, sizeof(buf), f)) { line++; - /* Parse IMSI Ki OPc AMF SQN */ + /* Parse IMSI Ki OPc AMF SQN [RES_len] */ buf[sizeof(buf) - 1] = '\0'; if (buf[0] == '#') continue; @@ -515,7 +521,19 @@ static int read_milenage(const char *fname) ret = -1; break; } - pos = pos2 + 1; + + if (pos2) { + pos = pos2 + 1; + m->res_len = atoi(pos); + if (m->res_len && + (m->res_len < EAP_AKA_RES_MIN_LEN || + m->res_len > EAP_AKA_RES_MAX_LEN)) { + printf("%s:%d - Invalid RES_len (%s)\n", + fname, line, pos); + ret = -1; + break; + } + } m->next = milenage_db; milenage_db = m; @@ -798,6 +816,10 @@ static int aka_req_auth(char *imsi, char *resp, size_t resp_len) } milenage_generate(m->opc, m->amf, m->ki, m->sqn, _rand, autn, ik, ck, res, &res_len); + if (m->res_len >= EAP_AKA_RES_MIN_LEN && + m->res_len <= EAP_AKA_RES_MAX_LEN && + m->res_len < res_len) + res_len = m->res_len; } else { printf("Unknown IMSI: %s\n", imsi); #ifdef AKA_USE_FIXED_TEST_VALUES diff --git a/hostapd/hlr_auc_gw.milenage_db b/hostapd/hlr_auc_gw.milenage_db index ecd06d720..c156a29ae 100644 --- a/hostapd/hlr_auc_gw.milenage_db +++ b/hostapd/hlr_auc_gw.milenage_db @@ -5,8 +5,10 @@ # authentication. In case of GSM/EAP-SIM, AMF and SQN values are not used, but # dummy values will need to be included in this file. -# IMSI Ki OPc AMF SQN +# IMSI Ki OPc AMF SQN [RES_len] 232010000000000 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000 +# Example using truncated 32-bit RES instead of 64-bit default +232010000000001 90dca4eda45b53cf0f12d7c9c3bc6a89 cb9cccc4b9258e6dca4760379fb82581 61df 000000000000 4 # These values are from Test Set 19 which has the AMF separation bit set to 1 # and as such, is suitable for EAP-AKA' test.