aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2008-11-05 21:02:13 (GMT)
committerJouni Malinen <j@w1.fi>2008-11-05 21:02:13 (GMT)
commit2a24bb31991ff79ef8aa13f7e6bd4cc948429d15 (patch)
tree983f6b50592de27fbd8f12dde78c353d98713f9e
parent988ab690acfe470e2a7a6de6c0a4710744f06661 (diff)
downloadhostap-06-2a24bb31991ff79ef8aa13f7e6bd4cc948429d15.zip
hostap-06-2a24bb31991ff79ef8aa13f7e6bd4cc948429d15.tar.gz
hostap-06-2a24bb31991ff79ef8aa13f7e6bd4cc948429d15.tar.bz2
Added Milenage USIM emulator for EAP-AKA (can be used to simulate test
USIM card with a known private key; enable with CONFIG_USIM_SIMULATOR in .config and password="Ki:OPc:SQN" in network configuration).
-rwxr-xr-xbuild_release1
-rw-r--r--src/eap_peer/eap_aka.c69
-rw-r--r--src/hlr_auc_gw/milenage.c109
-rw-r--r--src/hlr_auc_gw/milenage.h3
-rw-r--r--wpa_supplicant/ChangeLog6
-rw-r--r--wpa_supplicant/Makefile5
-rw-r--r--wpa_supplicant/defconfig3
7 files changed, 171 insertions, 25 deletions
diff --git a/build_release b/build_release
index 66da32b..fd19536 100755
--- a/build_release
+++ b/build_release
@@ -79,6 +79,7 @@ LIBS_p += -L$WINLOCAL/lib
CONFIG_EAP_SIM=y
CONFIG_EAP_AKA=y
+CONFIG_USIM_SIMULATOR=y
CONFIG_EAP_LEAP=y
CONFIG_EAP_FAST=y
CONFIG_EAP_TLS=y
diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c
index 304e20a..0d3937a 100644
--- a/src/eap_peer/eap_aka.c
+++ b/src/eap_peer/eap_aka.c
@@ -20,6 +20,10 @@
#include "eap_common/eap_sim_common.h"
#include "sha1.h"
#include "crypto.h"
+#include "eap_peer/eap_config.h"
+#ifdef CONFIG_USIM_SIMULATOR
+#include "hlr_auc_gw/milenage.h"
+#endif /* CONFIG_USIM_SIMULATOR */
struct eap_aka_data {
@@ -116,12 +120,58 @@ static void eap_aka_deinit(struct eap_sm *sm, void *priv)
static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data)
{
+ struct eap_peer_config *conf;
+
wpa_printf(MSG_DEBUG, "EAP-AKA: UMTS authentication algorithm");
-#ifdef PCSC_FUNCS
- return scard_umts_auth(sm->scard_ctx, data->rand,
- data->autn, data->res, &data->res_len,
- data->ik, data->ck, data->auts);
-#else /* PCSC_FUNCS */
+
+ conf = eap_get_config(sm);
+ if (conf == NULL)
+ return -1;
+ if (conf->pcsc) {
+ return scard_umts_auth(sm->scard_ctx, data->rand,
+ data->autn, data->res, &data->res_len,
+ data->ik, data->ck, data->auts);
+ }
+
+#ifdef CONFIG_USIM_SIMULATOR
+ if (conf->password) {
+ u8 opc[16], k[16], sqn[6];
+ const char *pos;
+ wpa_printf(MSG_DEBUG, "EAP-AKA: Use internal Milenage "
+ "implementation for UMTS authentication");
+ if (conf->password_len < 78) {
+ wpa_printf(MSG_DEBUG, "EAP-AKA: invalid Milenage "
+ "password");
+ return -1;
+ }
+ pos = (const char *) conf->password;
+ if (hexstr2bin(pos, k, 16))
+ return -1;
+ pos += 32;
+ if (*pos != ':')
+ return -1;
+ pos++;
+
+ if (hexstr2bin(pos, opc, 16))
+ return -1;
+ pos += 32;
+ if (*pos != ':')
+ return -1;
+ pos++;
+
+ if (hexstr2bin(pos, sqn, 6))
+ return -1;
+
+ return milenage_check(opc, k, sqn, data->rand, data->autn,
+ data->ik, data->ck,
+ data->res, &data->res_len, data->auts);
+ }
+#endif /* CONFIG_USIM_SIMULATOR */
+
+#ifdef CONFIG_USIM_HARDCODED
+ wpa_printf(MSG_DEBUG, "EAP-AKA: Use hardcoded Kc and SRES values for "
+ "testing");
+
/* These hardcoded Kc and SRES values are used for testing.
* Could consider making them configurable. */
os_memset(data->res, '2', EAP_AKA_RES_MAX_LEN);
@@ -148,7 +198,14 @@ static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data)
}
#endif
return 0;
-#endif /* PCSC_FUNCS */
+
+#else /* CONFIG_USIM_HARDCODED */
+
+ wpa_printf(MSG_DEBUG, "EAP-AKA: No UMTS authentication algorith "
+ "enabled");
+ return -1;
+
+#endif /* CONFIG_USIM_HARDCODED */
}
diff --git a/src/hlr_auc_gw/milenage.c b/src/hlr_auc_gw/milenage.c
index 666cfc3..26acf31 100644
--- a/src/hlr_auc_gw/milenage.c
+++ b/src/hlr_auc_gw/milenage.c
@@ -52,9 +52,9 @@ static int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
return -1;
/* tmp2 = IN1 = SQN || AMF || SQN || AMF */
- memcpy(tmp2, sqn, 6);
- memcpy(tmp2 + 6, amf, 2);
- memcpy(tmp2 + 8, tmp2, 8);
+ os_memcpy(tmp2, sqn, 6);
+ os_memcpy(tmp2 + 6, amf, 2);
+ os_memcpy(tmp2 + 8, tmp2, 8);
/* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */
@@ -72,9 +72,9 @@ static int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
for (i = 0; i < 16; i++)
tmp1[i] ^= opc[i];
if (mac_a)
- memcpy(mac_a, tmp1, 8); /* f1 */
+ os_memcpy(mac_a, tmp1, 8); /* f1 */
if (mac_s)
- memcpy(mac_s, tmp1 + 8, 8); /* f1* */
+ os_memcpy(mac_s, tmp1 + 8, 8); /* f1* */
return 0;
}
@@ -119,9 +119,9 @@ static int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
for (i = 0; i < 16; i++)
tmp3[i] ^= opc[i];
if (res)
- memcpy(res, tmp3 + 8, 8); /* f2 */
+ os_memcpy(res, tmp3 + 8, 8); /* f2 */
if (ak)
- memcpy(ak, tmp3, 6); /* f5 */
+ os_memcpy(ak, tmp3, 6); /* f5 */
/* f3 */
if (ck) {
@@ -181,7 +181,7 @@ void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
u8 *ck, u8 *res, size_t *res_len)
{
int i;
- u8 mac_a[16], ak[6];
+ u8 mac_a[8], ak[6];
if (*res_len < 8) {
*res_len = 0;
@@ -197,8 +197,8 @@ void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
/* AUTN = (SQN ^ AK) || AMF || MAC */
for (i = 0; i < 6; i++)
autn[i] = sqn[i] ^ ak[i];
- memcpy(autn + 6, amf, 2);
- memcpy(autn + 8, mac_a, 8);
+ os_memcpy(autn + 6, amf, 2);
+ os_memcpy(autn + 8, mac_a, 8);
}
@@ -250,7 +250,7 @@ int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc)
kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8];
#ifdef GSM_MILENAGE_ALT_SRES
- memcpy(sres, res, 4);
+ os_memcpy(sres, res, 4);
#else /* GSM_MILENAGE_ALT_SRES */
for (i = 0; i < 4; i++)
sres[i] = res[i] ^ res[i + 4];
@@ -259,6 +259,76 @@ int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc)
}
+/**
+ * milenage_generate - Generate AKA AUTN,IK,CK,RES
+ * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
+ * @k: K = 128-bit subscriber key
+ * @sqn: SQN = 48-bit sequence number
+ * @_rand: RAND = 128-bit random challenge
+ * @autn: AUTN = 128-bit authentication token
+ * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
+ * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
+ * @res: Buffer for RES = 64-bit signed response (f2), or %NULL
+ * @res_len: Variable that will be set to RES length
+ * @auts: 112-bit buffer for AUTS
+ * Returns: 0 on success, -1 on failure, or -2 on synchronization failure
+ */
+int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
+ const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
+ u8 *auts)
+{
+ int i;
+ u8 mac_a[8], ak[6], rx_sqn[6];
+ const u8 *amf;
+
+ wpa_hexdump(MSG_DEBUG, "Milenage: AUTN", autn, 16);
+ wpa_hexdump(MSG_DEBUG, "Milenage: RAND", _rand, 16);
+
+ if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
+ return -1;
+
+ *res_len = 8;
+ wpa_hexdump_key(MSG_DEBUG, "Milenage: RES", res, *res_len);
+ wpa_hexdump_key(MSG_DEBUG, "Milenage: CK", ck, 6);
+ wpa_hexdump_key(MSG_DEBUG, "Milenage: IK", ik, 6);
+ wpa_hexdump_key(MSG_DEBUG, "Milenage: AK", ak, 6);
+
+ /* AUTN = (SQN ^ AK) || AMF || MAC */
+ for (i = 0; i < 6; i++)
+ rx_sqn[i] = autn[i] ^ ak[i];
+ wpa_hexdump(MSG_DEBUG, "Milenage: SQN", rx_sqn, 6);
+
+ if (os_memcmp(rx_sqn, sqn, 6) <= 0) {
+ u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
+ if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
+ return -1;
+ wpa_hexdump_key(MSG_DEBUG, "Milenage: AK*", ak, 6);
+ for (i = 0; i < 6; i++)
+ auts[i] = sqn[i] ^ ak[i];
+ if (milenage_f1(opc, k, _rand, sqn, auts_amf, NULL, auts + 6))
+ return -1;
+ wpa_hexdump(MSG_DEBUG, "Milenage: AUTS", auts, 14);
+ return -2;
+ }
+
+ amf = autn + 6;
+ wpa_hexdump(MSG_DEBUG, "Milenage: AMF", amf, 2);
+ if (milenage_f1(opc, k, _rand, rx_sqn, amf, mac_a, NULL))
+ return -1;
+
+ wpa_hexdump(MSG_DEBUG, "Milenage: MAC_A", mac_a, 8);
+
+ if (os_memcmp(mac_a, autn + 8, 8) != 0) {
+ wpa_printf(MSG_DEBUG, "Milenage: MAC mismatch");
+ wpa_hexdump(MSG_DEBUG, "Milenage: Received MAC_A",
+ autn + 8, 8);
+ return -1;
+ }
+
+ return 0;
+}
+
+
#ifdef TEST_MAIN_MILENAGE
extern int wpa_debug_level;
@@ -1006,17 +1076,18 @@ int main(int argc, char *argv[])
}
printf("milenage_auts test:\n");
- memcpy(auts, "\x4f\x20\x39\x39\x2d\xdd", 6);
- memcpy(auts + 6, "\x4b\xb4\x31\x6e\xd4\xa1\x46\x88", 8);
+ os_memcpy(auts, "\x4f\x20\x39\x39\x2d\xdd", 6);
+ os_memcpy(auts + 6, "\x4b\xb4\x31\x6e\xd4\xa1\x46\x88", 8);
res = milenage_auts(t->opc, t->k, t->rand, auts, buf);
printf("AUTS for test set %d: %d / SQN=%02x%02x%02x%02x%02x%02x\n",
i, res, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
if (res)
ret++;
- memset(_rand, 0xaa, sizeof(_rand));
- memcpy(auts,
- "\x43\x68\x1a\xd3\xda\xf0\x06\xbc\xde\x40\x5a\x20\x72\x67", 14);
+ os_memset(_rand, 0xaa, sizeof(_rand));
+ os_memcpy(auts,
+ "\x43\x68\x1a\xd3\xda\xf0\x06\xbc\xde\x40\x5a\x20\x72\x67",
+ 14);
res = milenage_auts(t->opc, t->k, _rand, auts, buf);
printf("AUTS from a test USIM: %d / SQN=%02x%02x%02x%02x%02x%02x\n",
res, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
@@ -1024,9 +1095,9 @@ int main(int argc, char *argv[])
ret++;
printf("milenage_generate test:\n");
- memcpy(sqn, "\x00\x00\x00\x00\x40\x44", 6);
- memcpy(_rand, "\x12\x69\xb8\x23\x41\x39\x35\x66\xfb\x99\x41\xe9\x84"
- "\x4f\xe6\x2f", 16);
+ os_memcpy(sqn, "\x00\x00\x00\x00\x40\x44", 6);
+ os_memcpy(_rand, "\x12\x69\xb8\x23\x41\x39\x35\x66\xfb\x99\x41\xe9\x84"
+ "\x4f\xe6\x2f", 16);
res_len = 8;
milenage_generate(t->opc, t->amf, t->k, sqn, _rand, buf, buf2, buf3,
buf4, &res_len);
diff --git a/src/hlr_auc_gw/milenage.h b/src/hlr_auc_gw/milenage.h
index 6855459..b35603c 100644
--- a/src/hlr_auc_gw/milenage.h
+++ b/src/hlr_auc_gw/milenage.h
@@ -22,5 +22,8 @@ int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts,
u8 *sqn);
int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres,
u8 *kc);
+int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
+ const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
+ u8 *auts);
#endif /* MILENAGE_H */
diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog
index 4dc7f31..3917392 100644
--- a/wpa_supplicant/ChangeLog
+++ b/wpa_supplicant/ChangeLog
@@ -1,5 +1,11 @@
ChangeLog for wpa_supplicant
+????-??-?? - v0.6.6
+ * added Milenage USIM emulator for EAP-AKA (can be used to simulate
+ test USIM card with a known private key; enable with
+ CONFIG_USIM_SIMULATOR in .config and password="Ki:OPc:SQN" in
+ network configuration)
+
2008-11-01 - v0.6.5
* added support for SHA-256 as X.509 certificate digest when using the
internal X.509/TLSv1 implementation
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 1bdac6c..79b3e13 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -578,6 +578,11 @@ LIBS += -lpcsclite -lpthread
endif
endif
+ifdef CONFIG_USIM_SIMULATOR
+CFLAGS += -DCONFIG_USIM_SIMULATOR
+OBJS += ../src/hlr_auc_gw/milenage.o
+endif
+
ifndef CONFIG_TLS
CONFIG_TLS=openssl
endif
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index 2ad2bb8..38435cd 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -153,6 +153,9 @@ CONFIG_EAP_LEAP=y
# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
#CONFIG_EAP_AKA=y
+# Enable USIM simulator (Milenage) for EAP-AKA
+#CONFIG_USIM_SIMULATOR=y
+
# EAP-SAKE
#CONFIG_EAP_SAKE=y