static int eap_aka_umts_auth(struct eap_sm *sm, struct eap_aka_data *data) { 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 */ /* 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); data->res_len = EAP_AKA_RES_MAX_LEN; os_memset(data->ik, '3', EAP_AKA_IK_LEN); os_memset(data->ck, '4', EAP_AKA_CK_LEN); { u8 autn[EAP_AKA_AUTN_LEN]; os_memset(autn, '1', EAP_AKA_AUTN_LEN); if (os_memcmp(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) { wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match " "with expected value"); return -1; } } #if 0 { static int test_resync = 1; if (test_resync) { /* Test Resynchronization */ test_resync = 0; return -2; } } #endif return 0; #endif /* PCSC_FUNCS */ }
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"); 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); data->res_len = EAP_AKA_RES_MAX_LEN; os_memset(data->ik, '3', EAP_AKA_IK_LEN); os_memset(data->ck, '4', EAP_AKA_CK_LEN); { u8 autn[EAP_AKA_AUTN_LEN]; os_memset(autn, '1', EAP_AKA_AUTN_LEN); if (os_memcmp(autn, data->autn, EAP_AKA_AUTN_LEN) != 0) { wpa_printf(MSG_WARNING, "EAP-AKA: AUTN did not match " "with expected value"); return -1; } } #if 0 { static int test_resync = 1; if (test_resync) { /* Test Resynchronization */ test_resync = 0; return -2; } } #endif return 0; #else /* CONFIG_USIM_HARDCODED */ wpa_printf(MSG_DEBUG, "EAP-AKA: No UMTS authentication algorith " "enabled"); return -1; #endif /* CONFIG_USIM_HARDCODED */ }
static int scard_test(void) { struct scard_data *scard; size_t len; char imsi[20]; unsigned char _rand[16]; #ifdef PCSC_FUNCS unsigned char sres[4]; unsigned char kc[8]; #endif /* PCSC_FUNCS */ #define num_triplets 5 unsigned char rand_[num_triplets][16]; unsigned char sres_[num_triplets][4]; unsigned char kc_[num_triplets][8]; int i, res; size_t j; #define AKA_RAND_LEN 16 #define AKA_AUTN_LEN 16 #define AKA_AUTS_LEN 14 #define RES_MAX_LEN 16 #define IK_LEN 16 #define CK_LEN 16 unsigned char aka_rand[AKA_RAND_LEN]; unsigned char aka_autn[AKA_AUTN_LEN]; unsigned char aka_auts[AKA_AUTS_LEN]; unsigned char aka_res[RES_MAX_LEN]; size_t aka_res_len; unsigned char aka_ik[IK_LEN]; unsigned char aka_ck[CK_LEN]; scard = scard_init(SCARD_TRY_BOTH); if (scard == NULL) return -1; if (scard_set_pin(scard, "1234")) { wpa_printf(MSG_WARNING, "PIN validation failed"); scard_deinit(scard); return -1; } len = sizeof(imsi); if (scard_get_imsi(scard, imsi, &len)) goto failed; wpa_hexdump_ascii(MSG_DEBUG, "SCARD: IMSI", (u8 *) imsi, len); /* NOTE: Permanent Username: 1 | IMSI */ os_memset(_rand, 0, sizeof(_rand)); if (scard_gsm_auth(scard, _rand, sres, kc)) goto failed; os_memset(_rand, 0xff, sizeof(_rand)); if (scard_gsm_auth(scard, _rand, sres, kc)) goto failed; for (i = 0; i < num_triplets; i++) { os_memset(rand_[i], i, sizeof(rand_[i])); if (scard_gsm_auth(scard, rand_[i], sres_[i], kc_[i])) goto failed; } for (i = 0; i < num_triplets; i++) { printf("1"); for (j = 0; j < len; j++) printf("%c", imsi[j]); printf(","); for (j = 0; j < 16; j++) printf("%02X", rand_[i][j]); printf(","); for (j = 0; j < 4; j++) printf("%02X", sres_[i][j]); printf(","); for (j = 0; j < 8; j++) printf("%02X", kc_[i][j]); printf("\n"); } wpa_printf(MSG_DEBUG, "Trying to use UMTS authentication"); /* seq 39 (0x28) */ os_memset(aka_rand, 0xaa, 16); os_memcpy(aka_autn, "\x86\x71\x31\xcb\xa2\xfc\x61\xdf" "\xa3\xb3\x97\x9d\x07\x32\xa2\x12", 16); res = scard_umts_auth(scard, aka_rand, aka_autn, aka_res, &aka_res_len, aka_ik, aka_ck, aka_auts); if (res == 0) { wpa_printf(MSG_DEBUG, "UMTS auth completed successfully"); wpa_hexdump(MSG_DEBUG, "RES", aka_res, aka_res_len); wpa_hexdump(MSG_DEBUG, "IK", aka_ik, IK_LEN); wpa_hexdump(MSG_DEBUG, "CK", aka_ck, CK_LEN); } else if (res == -2) { wpa_printf(MSG_DEBUG, "UMTS auth resulted in synchronization " "failure"); wpa_hexdump(MSG_DEBUG, "AUTS", aka_auts, AKA_AUTS_LEN); } else { wpa_printf(MSG_DEBUG, "UMTS auth failed"); } failed: scard_deinit(scard); return 0; #undef num_triplets }