From 8ab7a3708910c0f572084e7dabff10d7c8ee3734 Mon Sep 17 00:00:00 2001 From: Simon Baatz Date: Sun, 22 Jan 2012 19:28:24 +0200 Subject: [PATCH] SIM/USIM: Add function to get the MNC length from the SIM/USIM The EF-AD (administrative data) file may contain information about the length of the MNC (2 or 3 digits) in the IMSI. This can be used to construct the realm according to 3GPP TS 23.003 during EAP-SIM or EAP-AKA authentication. Signed-hostap: Simon Baatz --- src/utils/pcsc_funcs.c | 55 ++++++++++++++++++++++++++++++++++++++++++ src/utils/pcsc_funcs.h | 2 ++ 2 files changed, 57 insertions(+) diff --git a/src/utils/pcsc_funcs.c b/src/utils/pcsc_funcs.c index c36193e4f..aecc6f7a4 100644 --- a/src/utils/pcsc_funcs.c +++ b/src/utils/pcsc_funcs.c @@ -1023,6 +1023,61 @@ int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len) } +/** + * scard_get_mnc_len - Read length of MNC in the IMSI from SIM/USIM card + * @scard: Pointer to private data from scard_init() + * Returns: length (>0) on success, -1 if administrative data file cannot be + * selected, -2 if administrative data file selection returns invalid result + * code, -3 if parsing FSP template file fails (USIM only), -4 if length of + * the file is unexpected, -5 if reading file fails, -6 if MNC length is not + * in range (i.e. 2 or 3), -7 if MNC length is not available. + * + */ +int scard_get_mnc_len(struct scard_data *scard) +{ + unsigned char buf[100]; + size_t blen; + int file_size; + + wpa_printf(MSG_DEBUG, "SCARD: reading MNC len from (GSM) EF-AD"); + blen = sizeof(buf); + if (scard_select_file(scard, SCARD_FILE_GSM_EF_AD, buf, &blen)) + return -1; + if (blen < 4) { + wpa_printf(MSG_WARNING, "SCARD: too short (GSM) EF-AD " + "header (len=%ld)", (long) blen); + return -2; + } + + if (scard->sim_type == SCARD_GSM_SIM) { + file_size = (buf[2] << 8) | buf[3]; + } else { + if (scard_parse_fsp_templ(buf, blen, NULL, &file_size)) + return -3; + } + if (file_size == 3) { + wpa_printf(MSG_DEBUG, "SCARD: MNC length not available"); + return -7; + } + if (file_size < 4 || file_size > sizeof(buf)) { + wpa_printf(MSG_DEBUG, "SCARD: invalid file length=%ld", + (long) file_size); + return -4; + } + + if (scard_read_file(scard, buf, file_size)) + return -5; + buf[3] = buf[3] & 0x0f; /* upper nibble reserved for future use */ + if (buf[3] < 2 || buf[3] > 3) { + wpa_printf(MSG_DEBUG, "SCARD: invalid MNC length=%ld", + (long) buf[3]); + return -6; + } + wpa_printf(MSG_DEBUG, "SCARD: MNC length=%ld", (long) buf[3]); + return buf[3]; +} + + /** * scard_gsm_auth - Run GSM authentication command on SIM card * @scard: Pointer to private data from scard_init() diff --git a/src/utils/pcsc_funcs.h b/src/utils/pcsc_funcs.h index 543f7c598..483247b9b 100644 --- a/src/utils/pcsc_funcs.h +++ b/src/utils/pcsc_funcs.h @@ -26,6 +26,7 @@ #define SCARD_FILE_GSM_DF 0x7F20 #define SCARD_FILE_UMTS_DF 0x7F50 #define SCARD_FILE_GSM_EF_IMSI 0x6F07 +#define SCARD_FILE_GSM_EF_AD 0x6FAD #define SCARD_FILE_EF_DIR 0x2F00 #define SCARD_FILE_EF_ICCID 0x2FE2 #define SCARD_FILE_EF_CK 0x6FE1 @@ -47,6 +48,7 @@ void scard_deinit(struct scard_data *scard); int scard_set_pin(struct scard_data *scard, const char *pin); int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len); +int scard_get_mnc_len(struct scard_data *scard); int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, unsigned char *sres, unsigned char *kc); int scard_umts_auth(struct scard_data *scard, const unsigned char *_rand, -- 2.39.2