static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data) { struct eap_peer_config *conf; wpa_printf(MSG_DEBUG, "EAP-SIM: GSM authentication algorithm"); conf = eap_get_config(sm); if (conf == NULL) return -1; if (conf->pcsc) { if (scard_gsm_auth(sm->scard_ctx, data->rand[0], data->sres[0], data->kc[0]) || scard_gsm_auth(sm->scard_ctx, data->rand[1], data->sres[1], data->kc[1]) || (data->num_chal > 2 && scard_gsm_auth(sm->scard_ctx, data->rand[2], data->sres[2], data->kc[2]))) { wpa_printf(MSG_DEBUG, "EAP-SIM: GSM SIM " "authentication could not be completed"); return -1; } return 0; } #ifdef CONFIG_SIM_SIMULATOR if (conf->password) { u8 opc[16], k[16]; const char *pos; size_t i; wpa_printf(MSG_DEBUG, "EAP-SIM: Use internal GSM-Milenage " "implementation for authentication"); if (conf->password_len < 65) { wpa_printf(MSG_DEBUG, "EAP-SIM: invalid GSM-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; for (i = 0; i < data->num_chal; i++) { if (gsm_milenage(opc, k, data->rand[i], data->sres[i], data->kc[i])) { wpa_printf(MSG_DEBUG, "EAP-SIM: " "GSM-Milenage authentication " "could not be completed"); return -1; } wpa_hexdump(MSG_DEBUG, "EAP-SIM: RAND", data->rand[i], GSM_RAND_LEN); wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: SRES", data->sres[i], EAP_SIM_SRES_LEN); wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: Kc", data->kc[i], EAP_SIM_KC_LEN); } return 0; } #endif /* CONFIG_SIM_SIMULATOR */ #ifdef CONFIG_SIM_HARDCODED /* These hardcoded Kc and SRES values are used for testing. RAND to * KC/SREC mapping is very bogus as far as real authentication is * concerned, but it is quite useful for cases where the AS is rotating * the order of pre-configured values. */ { size_t i; wpa_printf(MSG_DEBUG, "EAP-SIM: Use hardcoded Kc and SRES " "values for testing"); for (i = 0; i < data->num_chal; i++) { if (data->rand[i][0] == 0xaa) { os_memcpy(data->kc[i], "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7", EAP_SIM_KC_LEN); os_memcpy(data->sres[i], "\xd1\xd2\xd3\xd4", EAP_SIM_SRES_LEN); } else if (data->rand[i][0] == 0xbb) { os_memcpy(data->kc[i], "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7", EAP_SIM_KC_LEN); os_memcpy(data->sres[i], "\xe1\xe2\xe3\xe4", EAP_SIM_SRES_LEN); } else { os_memcpy(data->kc[i], "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7", EAP_SIM_KC_LEN); os_memcpy(data->sres[i], "\xf1\xf2\xf3\xf4", EAP_SIM_SRES_LEN); } } } return 0; #else /* CONFIG_SIM_HARDCODED */ wpa_printf(MSG_DEBUG, "EAP-SIM: No GSM authentication algorithm " "enabled"); return -1; #endif /* CONFIG_SIM_HARDCODED */ }
int main(int argc, char *argv[]) { u8 buf[16], buf2[16], buf3[16], buf4[16], buf5[16], opc[16]; u8 auts[14], sqn[6], _rand[16]; int ret = 0, res, i; const struct milenage_test_set *t; size_t res_len; wpa_debug_level = 0; printf("Milenage test sets\n"); for (i = 0; i < NUM_TESTS; i++) { t = &test_sets[i]; printf("Test Set %d\n", i + 1); milenage_opc(t->op, t->k, opc); if (memcmp(opc, t->opc, 16) != 0) { printf("- milenage_opc failed\n"); ret++; } if (milenage_f1(opc, t->k, t->rand, t->sqn, t->amf, buf, buf2) || memcmp(buf, t->f1, 8) != 0) { printf("- milenage_f1 failed\n"); ret++; } if (memcmp(buf2, t->f1star, 8) != 0) { printf("- milenage_f1* failed\n"); ret++; } if (milenage_f2345(opc, t->k, t->rand, buf, buf2, buf3, buf4, buf5) || memcmp(buf, t->f2, 8) != 0) { printf("- milenage_f2 failed\n"); ret++; } if (memcmp(buf2, t->f3, 16) != 0) { printf("- milenage_f3 failed\n"); ret++; } if (memcmp(buf3, t->f4, 16) != 0) { printf("- milenage_f4 failed\n"); ret++; } if (memcmp(buf4, t->f5, 6) != 0) { printf("- milenage_f5 failed\n"); ret++; } if (memcmp(buf5, t->f5star, 6) != 0) { printf("- milenage_f5* failed\n"); ret++; } } printf("milenage_auts test:\n"); 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++; 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]); if (res) ret++; printf("milenage_generate test:\n"); 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); wpa_hexdump(MSG_DEBUG, "SQN", sqn, 6); wpa_hexdump(MSG_DEBUG, "RAND", _rand, 16); wpa_hexdump(MSG_DEBUG, "AUTN", buf, 16); wpa_hexdump(MSG_DEBUG, "IK", buf2, 16); wpa_hexdump(MSG_DEBUG, "CK", buf3, 16); wpa_hexdump(MSG_DEBUG, "RES", buf4, res_len); printf("GSM-Milenage test sets\n"); for (i = 0; i < NUM_GSM_TESTS; i++) { const struct gsm_milenage_test_set *g; u8 sres[4], kc[8]; g = &gsm_test_sets[i]; printf("Test Set %d\n", i + 1); gsm_milenage(g->opc, g->ki, g->rand, sres, kc); if (memcmp(g->kc, kc, 8) != 0) { printf("- gsm_milenage Kc failed\n"); ret++; } #ifdef GSM_MILENAGE_ALT_SRES if (memcmp(g->sres2, sres, 4) != 0) { printf("- gsm_milenage SRES#2 failed\n"); ret++; } #else /* GSM_MILENAGE_ALT_SRES */ if (memcmp(g->sres1, sres, 4) != 0) { printf("- gsm_milenage SRES#1 failed\n"); ret++; } #endif /* GSM_MILENAGE_ALT_SRES */ } if (ret) printf("Something failed\n"); else printf("OK\n"); return ret; }