/** Milenage check * * @param[out] ik Buffer for IK = 128-bit integrity key (f4), or NULL. * @param[out] ck Buffer for CK = 128-bit confidentiality key (f3), or NULL. * @param[out] res Buffer for RES = 64-bit signed response (f2), or NULL. * @param[in] auts 112-bit buffer for AUTS. * @param[in] opc 128-bit operator variant algorithm configuration field (encr.). * @param[in] ki 128-bit subscriber key. * @param[in] sqn 48-bit sequence number. * @param[in] rand 128-bit random challenge. * @param[in] autn 128-bit authentication token. * @return * - 0 on success. * - -1 on failure. * - -2 on synchronization failure */ int milenage_check(uint8_t ik[MILENAGE_IK_SIZE], uint8_t ck[MILENAGE_CK_SIZE], uint8_t res[MILENAGE_RES_SIZE], uint8_t auts[MILENAGE_AUTS_SIZE], uint8_t const opc[MILENAGE_OPC_SIZE], uint8_t const ki[MILENAGE_KI_SIZE], uint64_t sqn, uint8_t const rand[MILENAGE_RAND_SIZE], uint8_t const autn[MILENAGE_AUTN_SIZE]) { uint8_t mac_a[MILENAGE_MAC_A_SIZE], ak[MILENAGE_AK_SIZE], rx_sqn[MILENAGE_SQN_SIZE]; uint8_t sqn_buff[MILENAGE_SQN_SIZE]; const uint8_t *amf; size_t i; uint48_to_buff(sqn_buff, sqn); FR_PROTO_HEX_DUMP(autn, MILENAGE_AUTN_SIZE, "AUTN"); FR_PROTO_HEX_DUMP(rand, MILENAGE_RAND_SIZE, "RAND"); if (milenage_f2345(res, ck, ik, ak, NULL, opc, ki, rand)) return -1; FR_PROTO_HEX_DUMP(res, MILENAGE_RES_SIZE, "RES"); FR_PROTO_HEX_DUMP(ck, MILENAGE_CK_SIZE, "CK"); FR_PROTO_HEX_DUMP(ik, MILENAGE_IK_SIZE, "IK"); FR_PROTO_HEX_DUMP(ak, MILENAGE_AK_SIZE, "AK"); /* AUTN = (SQN ^ AK) || AMF || MAC */ for (i = 0; i < 6; i++) rx_sqn[i] = autn[i] ^ ak[i]; FR_PROTO_HEX_DUMP(rx_sqn, MILENAGE_SQN_SIZE, "SQN"); if (memcmp(rx_sqn, sqn_buff, sizeof(rx_sqn)) <= 0) { uint8_t auts_amf[MILENAGE_AMF_SIZE] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ if (milenage_f2345(NULL, NULL, NULL, NULL, ak, opc, ki, rand)) return -1; FR_PROTO_HEX_DUMP(ak, sizeof(ak), "AK*"); for (i = 0; i < 6; i++) auts[i] = sqn_buff[i] ^ ak[i]; if (milenage_f1(NULL, auts + 6, opc, ki, rand, sqn_buff, auts_amf) < 0) return -1; FR_PROTO_HEX_DUMP(auts, 14, "AUTS"); return -2; } amf = autn + 6; FR_PROTO_HEX_DUMP(amf, MILENAGE_AMF_SIZE, "AMF"); if (milenage_f1(mac_a, NULL, opc, ki, rand, rx_sqn, amf) < 0) return -1; FR_PROTO_HEX_DUMP(mac_a, MILENAGE_MAC_A_SIZE, "MAC_A"); if (CRYPTO_memcmp(mac_a, autn + 8, 8) != 0) { FR_PROTO_HEX_DUMP(autn + 8, 8, "Received MAC_A"); fr_strerror_printf("MAC mismatch"); return -1; } return 0; }
/** * 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, 16); wpa_hexdump_key(MSG_DEBUG, "Milenage: IK", ik, 16); 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; }
/** Generate AKA AUTN, IK, CK, RES * * @param[out] autn Buffer for AUTN = 128-bit authentication token. * @param[out] ik Buffer for IK = 128-bit integrity key (f4), or NULL. * @param[out] ck Buffer for CK = 128-bit confidentiality key (f3), or NULL. * @param[out] ak Buffer for AK = 48-bit anonymity key (f5), or NULL * @param[out] res Buffer for RES = 64-bit signed response (f2), or NULL. * @param[in] opc 128-bit operator variant algorithm configuration field (encr.). * @param[in] amf 16-bit authentication management field. * @param[in] ki 128-bit subscriber key. * @param[in] sqn 48-bit sequence number (host byte order). * @param[in] rand 128-bit random challenge. * @return * - 0 on success. * - -1 on failure. */ int milenage_umts_generate(uint8_t autn[MILENAGE_AUTN_SIZE], uint8_t ik[MILENAGE_IK_SIZE], uint8_t ck[MILENAGE_CK_SIZE], uint8_t ak[MILENAGE_AK_SIZE], uint8_t res[MILENAGE_RES_SIZE], uint8_t const opc[MILENAGE_OPC_SIZE], uint8_t const amf[MILENAGE_AMF_SIZE], uint8_t const ki[MILENAGE_KI_SIZE], uint64_t sqn, uint8_t const rand[MILENAGE_RAND_SIZE]) { uint8_t mac_a[8], ak_buff[MILENAGE_AK_SIZE]; uint8_t sqn_buff[MILENAGE_SQN_SIZE]; uint8_t *p = autn; size_t i; if ((milenage_f1(mac_a, NULL, opc, ki, rand, uint48_to_buff(sqn_buff, sqn), amf) < 0) || (milenage_f2345(res, ik, ck, ak_buff, NULL, opc, ki, rand) < 0)) return -1; /* * AUTN = (SQN ^ AK) || AMF || MAC_A */ for (i = 0; i < sizeof(sqn_buff); i++) *p++ = sqn_buff[i] ^ ak_buff[i]; memcpy(p, amf, MILENAGE_AMF_SIZE); p += MILENAGE_AMF_SIZE; memcpy(p, mac_a, sizeof(mac_a)); /* * Output the anonymity key if required */ if (ak) memcpy(ak, ak_buff, sizeof(ak_buff)); return 0; }
/** Generate GSM-Milenage (3GPP TS 55.205) authentication triplet * * @param[out] sres Buffer for SRES = 32-bit SRES. * @param[out] kc 64-bit Kc. * @param[in] opc 128-bit operator variant algorithm configuration field (encr.). * @param[in] ki 128-bit subscriber key. * @param[in] rand 128-bit random challenge. * @return * - 0 on success. * - -1 on failure. */ int milenage_gsm_generate(uint8_t sres[MILENAGE_SRES_SIZE], uint8_t kc[MILENAGE_KC_SIZE], uint8_t const opc[MILENAGE_OPC_SIZE], uint8_t const ki[MILENAGE_KI_SIZE], uint8_t const rand[MILENAGE_RAND_SIZE]) { uint8_t res[MILENAGE_RES_SIZE], ck[MILENAGE_CK_SIZE], ik[MILENAGE_IK_SIZE]; if (milenage_f2345(res, ik, ck, NULL, NULL, opc, ki, rand)) return -1; milenage_gsm_from_umts(sres, kc, ik, ck, res); return 0; }
/** * milenage_auts - Milenage AUTS validation * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) * @k: K = 128-bit subscriber key * @_rand: RAND = 128-bit random challenge * @auts: AUTS = 112-bit authentication token from client * @sqn: Buffer for SQN = 48-bit sequence number * Returns: 0 = success (sqn filled), -1 on failure */ int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts, u8 *sqn) { u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ u8 ak[6], mac_s[8]; int i; if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak)) return -1; for (i = 0; i < 6; i++) sqn[i] = auts[i] ^ ak[i]; if (milenage_f1(opc, k, _rand, sqn, amf, NULL, mac_s) || memcmp(mac_s, auts + 6, 8) != 0) return -1; return 0; }
/** * gsm_milenage - Generate GSM-Milenage (3GPP TS 55.205) authentication triplet * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) * @k: K = 128-bit subscriber key * @_rand: RAND = 128-bit random challenge * @sres: Buffer for SRES = 32-bit SRES * @kc: Buffer for Kc = 64-bit Kc * Returns: 0 on success, -1 on failure */ int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc) { u8 res[8], ck[16], ik[16]; int i; if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL)) return -1; for (i = 0; i < 8; i++) kc[i] = ck[i] ^ ck[i + 8] ^ ik[i] ^ ik[i + 8]; #ifdef GSM_MILENAGE_ALT_SRES os_memcpy(sres, res, 4); #else /* GSM_MILENAGE_ALT_SRES */ for (i = 0; i < 4; i++) sres[i] = res[i] ^ res[i + 4]; #endif /* GSM_MILENAGE_ALT_SRES */ return 0; }
/** Milenage AUTS validation * * @param[out] sqn Buffer for SQN = 48-bit sequence number (host byte order). * @param[in] opc 128-bit operator variant algorithm configuration field (encr.). * @param[in] ki 128-bit subscriber key. * @param[in] rand 128-bit random challenge. * @param[in] auts 112-bit authentication token from client. * @return * - 0 on success with sqn filled. * - -1 on failure. */ int milenage_auts(uint64_t sqn, uint8_t const opc[MILENAGE_OPC_SIZE], uint8_t const ki[MILENAGE_KI_SIZE], uint8_t const rand[MILENAGE_RAND_SIZE], uint8_t const auts[MILENAGE_AUTS_SIZE]) { uint8_t amf[MILENAGE_AMF_SIZE] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */ uint8_t ak[MILENAGE_AK_SIZE], mac_s[MILENAGE_MAC_S_SIZE]; uint8_t sqn_buff[MILENAGE_SQN_SIZE]; size_t i; uint48_to_buff(sqn_buff, sqn); if (milenage_f2345(NULL, NULL, NULL, NULL, ak, opc, ki, rand)) return -1; for (i = 0; i < sizeof(sqn_buff); i++) sqn_buff[i] = auts[i] ^ ak[i]; if (milenage_f1(NULL, mac_s, opc, ki, rand, sqn_buff, amf) || CRYPTO_memcmp(mac_s, auts + 6, 8) != 0) return -1; return 0; }
/** * milenage_generate - Generate AKA AUTN,IK,CK,RES * @opc: OPc = 128-bit operator variant algorithm configuration field (encr.) * @amf: AMF = 16-bit authentication management field * @k: K = 128-bit subscriber key * @sqn: SQN = 48-bit sequence number * @_rand: RAND = 128-bit random challenge * @autn: Buffer for 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: Max length for res; set to used length or 0 on failure */ void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k, const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len) { int i; u8 mac_a[8], ak[6]; if (*res_len < 8) { *res_len = 0; return; } if (milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) || milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL)) { *res_len = 0; return; } *res_len = 8; /* AUTN = (SQN ^ AK) || AMF || MAC */ for (i = 0; i < 6; i++) autn[i] = sqn[i] ^ ak[i]; os_memcpy(autn + 6, amf, 2); os_memcpy(autn + 8, mac_a, 8); }
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; }
void test_set_19(void) { /* * Inputs */ uint8_t ki[] = { 0x51, 0x22, 0x25, 0x02, 0x14, 0xc3, 0x3e, 0x72, 0x3a, 0x5d, 0xd5, 0x23, 0xfc, 0x14, 0x5f, 0xc0 }; uint8_t rand[] = { 0x81, 0xe9, 0x2b, 0x6c, 0x0e, 0xe0, 0xe1, 0x2e, 0xbc, 0xeb, 0xa8, 0xd9, 0x2a, 0x99, 0xdf, 0xa5 }; uint8_t sqn[] = { 0x16, 0xf3, 0xb3, 0xf7, 0x0f, 0xc2 }; uint8_t amf[] = { 0xc3, 0xab }; uint8_t op[] = { 0xc9, 0xe8, 0x76, 0x32, 0x86, 0xb5, 0xb9, 0xff, 0xbd, 0xf5, 0x6e, 0x12, 0x97, 0xd0, 0x88, 0x7b }; uint8_t opc[] = { 0x98, 0x1d, 0x46, 0x4c, 0x7c, 0x52, 0xeb, 0x6e, 0x50, 0x36, 0x23, 0x49, 0x84, 0xad, 0x0b, 0xcf }; /* * Outputs */ uint8_t opc_out[MILENAGE_OPC_SIZE]; uint8_t mac_a_out[MILENAGE_MAC_A_SIZE]; uint8_t mac_s_out[MILENAGE_MAC_S_SIZE]; uint8_t res_out[MILENAGE_RES_SIZE]; uint8_t ck_out[MILENAGE_CK_SIZE]; uint8_t ik_out[MILENAGE_IK_SIZE]; uint8_t ak_out[MILENAGE_AK_SIZE]; uint8_t ak_resync_out[MILENAGE_AK_SIZE]; /* function 1 */ uint8_t mac_a[] = { 0x2a, 0x5c, 0x23, 0xd1, 0x5e, 0xe3, 0x51, 0xd5 }; /* function 1* */ uint8_t mac_s[] = { 0x62, 0xda, 0xe3, 0x85, 0x3f, 0x3a, 0xf9, 0xd2 }; /* function 2 */ uint8_t res[] = { 0x28, 0xd7, 0xb0, 0xf2, 0xa2, 0xec, 0x3d, 0xe5 }; /* function 3 */ uint8_t ck[] = { 0x53, 0x49, 0xfb, 0xe0, 0x98, 0x64, 0x9f, 0x94, 0x8f, 0x5d, 0x2e, 0x97, 0x3a, 0x81, 0xc0, 0x0f }; /* function 4 */ uint8_t ik[] = { 0x97, 0x44, 0x87, 0x1a, 0xd3, 0x2b, 0xf9, 0xbb, 0xd1, 0xdd, 0x5c, 0xe5, 0x4e, 0x3e, 0x2e, 0x5a }; /* function 5 */ uint8_t ak[] = { 0xad, 0xa1, 0x5a, 0xeb, 0x7b, 0xb8 }; /* function 5* */ uint8_t ak_resync[] = { 0xd4, 0x61, 0xbc, 0x15, 0x47, 0x5d }; int ret = 0; /* fr_log_fp = stdout; fr_debug_lvl = 4; */ ret = milenage_opc_generate(opc_out, op, ki); TEST_CHECK(ret == 0); FR_PROTO_HEX_DUMP(opc_out, sizeof(opc_out), "opc"); TEST_CHECK(memcmp(opc_out, opc, sizeof(opc_out)) == 0); if ((milenage_f1(mac_a_out, mac_s_out, opc, ki, rand, sqn, amf) < 0) || (milenage_f2345(res_out, ik_out, ck_out, ak_out, ak_resync_out, opc, ki, rand) < 0)) ret = -1; FR_PROTO_HEX_DUMP(mac_a, sizeof(mac_a_out), "mac_a"); FR_PROTO_HEX_DUMP(mac_s, sizeof(mac_s_out), "mac_s"); FR_PROTO_HEX_DUMP(ik_out, sizeof(ik_out), "ik"); FR_PROTO_HEX_DUMP(ck_out, sizeof(ck_out), "ck"); FR_PROTO_HEX_DUMP(res_out, sizeof(res_out), "res"); FR_PROTO_HEX_DUMP(ak_out, sizeof(ak_out), "ak"); FR_PROTO_HEX_DUMP(ak_resync_out, sizeof(ak_resync_out), "ak_resync"); TEST_CHECK(ret == 0); TEST_CHECK(memcmp(mac_a_out, mac_a, sizeof(mac_a_out)) == 0); TEST_CHECK(memcmp(mac_s_out, mac_s, sizeof(mac_s_out)) == 0); TEST_CHECK(memcmp(res_out, res, sizeof(res_out)) == 0); TEST_CHECK(memcmp(ck_out, ck, sizeof(ck_out)) == 0); TEST_CHECK(memcmp(ik_out, ik, sizeof(ik_out)) == 0); TEST_CHECK(memcmp(ak_out, ak, sizeof(ak_out)) == 0); TEST_CHECK(memcmp(ak_resync, ak_resync, sizeof(ak_resync_out)) == 0); }
void test_set_1(void) { /* * Inputs */ uint8_t ki[] = { 0x46, 0x5b, 0x5c, 0xe8, 0xb1, 0x99, 0xb4, 0x9f, 0xaa, 0x5f, 0x0a, 0x2e, 0xe2, 0x38, 0xa6, 0xbc }; uint8_t rand[] = { 0x23, 0x55, 0x3c, 0xbe, 0x96, 0x37, 0xa8, 0x9d, 0x21, 0x8a, 0xe6, 0x4d, 0xae, 0x47, 0xbf, 0x35 }; uint8_t sqn[] = { 0xff, 0x9b, 0xb4, 0xd0, 0xb6, 0x07 }; uint8_t amf[] = { 0xb9, 0xb9 }; uint8_t op[] = { 0xcd, 0xc2, 0x02, 0xd5, 0x12, 0x3e, 0x20, 0xf6, 0x2b, 0x6d, 0x67, 0x6a, 0xc7, 0x2c, 0xb3, 0x18 }; uint8_t opc[] = { 0xcd, 0x63, 0xcb, 0x71, 0x95, 0x4a, 0x9f, 0x4e, 0x48, 0xa5, 0x99, 0x4e, 0x37, 0xa0, 0x2b, 0xaf }; /* * Outputs */ uint8_t opc_out[MILENAGE_OPC_SIZE]; uint8_t mac_a_out[MILENAGE_MAC_A_SIZE]; uint8_t mac_s_out[MILENAGE_MAC_S_SIZE]; uint8_t res_out[MILENAGE_RES_SIZE]; uint8_t ck_out[MILENAGE_CK_SIZE]; uint8_t ik_out[MILENAGE_IK_SIZE]; uint8_t ak_out[MILENAGE_AK_SIZE]; uint8_t ak_resync_out[MILENAGE_AK_SIZE]; /* function 1 */ uint8_t mac_a[] = { 0x4a, 0x9f, 0xfa, 0xc3, 0x54, 0xdf, 0xaf, 0xb3 }; /* function 1* */ uint8_t mac_s[] = { 0x01, 0xcf, 0xaf, 0x9e, 0xc4, 0xe8, 0x71, 0xe9 }; /* function 2 */ uint8_t res[] = { 0xa5, 0x42, 0x11, 0xd5, 0xe3, 0xba, 0x50, 0xbf }; /* function 3 */ uint8_t ck[] = { 0xb4, 0x0b, 0xa9, 0xa3, 0xc5, 0x8b, 0x2a, 0x05, 0xbb, 0xf0, 0xd9, 0x87, 0xb2, 0x1b, 0xf8, 0xcb }; /* function 4 */ uint8_t ik[] = { 0xf7, 0x69, 0xbc, 0xd7, 0x51, 0x04, 0x46, 0x04, 0x12, 0x76, 0x72, 0x71, 0x1c, 0x6d, 0x34, 0x41 }; /* function 5 */ uint8_t ak[] = { 0xaa, 0x68, 0x9c, 0x64, 0x83, 0x70 }; /* function 5* */ uint8_t ak_resync[] = { 0x45, 0x1e, 0x8b, 0xec, 0xa4, 0x3b }; int ret = 0; /* fr_log_fp = stdout; fr_debug_lvl = 4; */ ret = milenage_opc_generate(opc_out, op, ki); TEST_CHECK(ret == 0); FR_PROTO_HEX_DUMP(opc_out, sizeof(opc_out), "opc"); TEST_CHECK(memcmp(opc_out, opc, sizeof(opc_out)) == 0); if ((milenage_f1(mac_a_out, mac_s_out, opc, ki, rand, sqn, amf) < 0) || (milenage_f2345(res_out, ik_out, ck_out, ak_out, ak_resync_out, opc, ki, rand) < 0)) ret = -1; FR_PROTO_HEX_DUMP(mac_a, sizeof(mac_a_out), "mac_a"); FR_PROTO_HEX_DUMP(mac_s, sizeof(mac_s_out), "mac_s"); FR_PROTO_HEX_DUMP(ik_out, sizeof(ik_out), "ik"); FR_PROTO_HEX_DUMP(ck_out, sizeof(ck_out), "ck"); FR_PROTO_HEX_DUMP(res_out, sizeof(res_out), "res"); FR_PROTO_HEX_DUMP(ak_out, sizeof(ak_out), "ak"); FR_PROTO_HEX_DUMP(ak_resync_out, sizeof(ak_resync_out), "ak_resync"); TEST_CHECK(ret == 0); TEST_CHECK(memcmp(mac_a_out, mac_a, sizeof(mac_a_out)) == 0); TEST_CHECK(memcmp(mac_s_out, mac_s, sizeof(mac_s_out)) == 0); TEST_CHECK(memcmp(res_out, res, sizeof(res_out)) == 0); TEST_CHECK(memcmp(ck_out, ck, sizeof(ck_out)) == 0); TEST_CHECK(memcmp(ik_out, ik, sizeof(ik_out)) == 0); TEST_CHECK(memcmp(ak_out, ak, sizeof(ak_out)) == 0); TEST_CHECK(memcmp(ak_resync, ak_resync, sizeof(ak_resync_out)) == 0); }