diff mbox

[3/4] SIM/USIM: Add function to get the MNC length from the SIM/USIM

Message ID 59615bfbda0d1a899675ac86b8018412736186a6.1326658542.git.gmbnomis@gmail.com
State Accepted
Commit 8ab7a3708910c0f572084e7dabff10d7c8ee3734
Headers show

Commit Message

Simon Baatz Jan. 15, 2012, 8:32 p.m. UTC
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 <gmbnomis@gmail.com>
---
 src/utils/pcsc_funcs.c |   52 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/utils/pcsc_funcs.h |    2 +
 2 files changed, 54 insertions(+), 0 deletions(-)

Comments

Jouni Malinen Jan. 22, 2012, 5:41 p.m. UTC | #1
On Sun, Jan 15, 2012 at 09:32:47PM +0100, Simon Baatz wrote:
> 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.

Thanks, applied. Though, I added a new return value for indicating that
the optional MNC length field was not present in EF_AD to make the debug
output somewhat cleaner.

The first SIM card I tested (prepaid Elisa/Kolumbus) this with happened
to not include the MNC length and the default assumption of 3-digit MNC
in the patch 4/4 was not the correct one for that card.. Unfortunately,
it looks like there would need to be a list of MCC/MNC values with the
MNC length for the automatic detection to work reliably (what a silly
design to make that field optional and not allow automatic way of
figuring out the correct field length).
Marcel Holtmann Jan. 22, 2012, 5:48 p.m. UTC | #2
Hi Jouni,

> > 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.
> 
> Thanks, applied. Though, I added a new return value for indicating that
> the optional MNC length field was not present in EF_AD to make the debug
> output somewhat cleaner.
> 
> The first SIM card I tested (prepaid Elisa/Kolumbus) this with happened
> to not include the MNC length and the default assumption of 3-digit MNC
> in the patch 4/4 was not the correct one for that card.. Unfortunately,
> it looks like there would need to be a list of MCC/MNC values with the
> MNC length for the automatic detection to work reliably (what a silly
> design to make that field optional and not allow automatic way of
> figuring out the correct field length).

this is not going to work. You can have operators that can mix and match
2 and 3 digit MNC as they please (within the same network). The field is
most likely present, but the SIM filesystem access might be broken. The
firmware for non-phone modems is really crappy in this area. Especially
the Qualcomm based ones are broken all over the places.

Regards

Marcel
Jouni Malinen Jan. 22, 2012, 6:50 p.m. UTC | #3
On Sun, Jan 22, 2012 at 06:48:16PM +0100, Marcel Holtmann wrote:
> this is not going to work. You can have operators that can mix and match
> 2 and 3 digit MNC as they please (within the same network).

Great. Well, I can use the 3-digit MNC as a default and add exceptions
as needed, I'd guess. The only SIM card that I found without the MNC
length field was for MCC=244 and all networks in Finland use 2-digit MNC
as far as I can tell..

> The field is
> most likely present, but the SIM filesystem access might be broken.

I don't think that that would have been the case in my tests. I used the
same reader for all the SIM cards and the AF_AD contents from the
Elisa/Kolumbus card returned three octets of data while the other cards
returned four octets.
diff mbox

Patch

diff --git a/src/utils/pcsc_funcs.c b/src/utils/pcsc_funcs.c
index c36193e..9c9f145 100644
--- a/src/utils/pcsc_funcs.c
+++ b/src/utils/pcsc_funcs.c
@@ -1024,6 +1024,58 @@  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).
+ *
+ */
+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 < 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()
  * @_rand: 16-byte RAND value from HLR/AuC
diff --git a/src/utils/pcsc_funcs.h b/src/utils/pcsc_funcs.h
index 543f7c5..483247b 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,