uint8_t *sqn_ms_derive(const uint8_t const opc[16], uint8_t *key, uint8_t *auts, uint8_t *rand_p) { /* AUTS = Conc(SQN MS ) || MAC-S * Conc(SQN MS ) = SQN MS ^ f5* (RAND) * MAC-S = f1* (SQN MS || RAND || AMF) */ uint8_t ak[6]; uint8_t *conc_sqn_ms; uint8_t *mac_s; uint8_t mac_s_computed[MAC_S_LENGTH]; uint8_t *sqn_ms; uint8_t amf[2] = { 0, 0 }; int i; conc_sqn_ms = auts; mac_s = &auts[6]; sqn_ms = malloc(SQN_LENGTH_OCTEST); /*if (hss_config.valid_opc == 0) { SetOP(hss_config.operator_key); }*/ /* Derive AK from key and rand */ f5star(opc, key, rand_p, ak); for (i = 0; i < 6; i++) { sqn_ms[i] = ak[i] ^ conc_sqn_ms[i]; } print_buffer("sqn_ms_derive() KEY : ", key, 16); print_buffer("sqn_ms_derive() RAND : ", rand_p, 16); print_buffer("sqn_ms_derive() AUTS : ", auts, 14); print_buffer("sqn_ms_derive() AK : ", ak, 6); print_buffer("sqn_ms_derive() SQN_MS : ", sqn_ms, 6); print_buffer("sqn_ms_derive() MAC_S : ", mac_s, 8); f1star(opc, key, rand_p, sqn_ms, amf, mac_s_computed); print_buffer("MAC_S +: ", mac_s_computed, 8); if (memcmp(mac_s_computed, mac_s, 8) != 0) { fprintf(stderr, "Failed to verify computed SQN_MS\n"); free(sqn_ms); return NULL; } return sqn_ms; }
static void do_f4f5star(uint8_t *key, uint8_t *rand, uint8_t *op, uint8_t *f4_exp, uint8_t *f5star_exp) { uint8_t res_f2[8]; uint8_t res_f5[6]; uint8_t res_f3[16]; uint8_t res_f4[16]; uint8_t res_f5star[6]; SetOPc(op); f2345(key, rand, res_f2, res_f3, res_f4, res_f5); if (compare_buffer(res_f4, 16, f4_exp, 16) != 0) { fail("Fail: f4"); } f5star(key, rand, res_f5star); if (compare_buffer(res_f5star, 6, f5star_exp, 6) != 0) { fail("Fail: f5star"); } }
/**************************************************************************** ** ** ** Name: usim_api_authenticate() ** ** ** ** Description: Performs mutual authentication of the USIM to the network,** ** checking whether authentication token AUTN can be accep- ** ** ted. If so, returns an authentication response RES and ** ** the ciphering and integrity keys. ** ** In case of synch failure, returns a re-synchronization ** ** token AUTS. ** ** ** ** 3GPP TS 31.102, section 7.1.1.1 ** ** ** ** Authentication and key generating function algorithms are ** ** specified in 3GPP TS 35.206. ** ** ** ** Inputs: rand_pP: Random challenge number ** ** autn_pP: Authentication token ** ** AUTN = (SQN xor AK) || AMF || MAC ** ** 48 16 64 bits ** ** Others: Security key ** ** ** ** Outputs: auts_pP: Re-synchronization token ** ** res_pP: Authentication response ** ** ck_pP: Ciphering key ** ** ik_pP Integrity key ** ** ** ** Return: RETURNerror, RETURNok ** ** Others: None ** ** ** ***************************************************************************/ int usim_api_authenticate(const OctetString* rand_pP, const OctetString* autn_pP, OctetString* auts_pP, OctetString* res_pP, OctetString* ck_pP, OctetString* ik_pP) { LOG_FUNC_IN; int rc; int i; LOG_TRACE(DEBUG, "USIM-API - rand :%s",dump_octet_string(rand_pP)); LOG_TRACE(DEBUG, "USIM-API - autn :%s",dump_octet_string(autn_pP)); /* Compute the authentication response RES = f2K (RAND) */ /* Compute the cipher key CK = f3K (RAND) */ /* Compute the integrity key IK = f4K (RAND) */ /* Compute the anonymity key AK = f5K (RAND) */ #define USIM_API_AK_SIZE 6 u8 ak[USIM_API_AK_SIZE]; f2345(_usim_api_k, rand_pP->value, res_pP->value, ck_pP->value, ik_pP->value, ak); LOG_TRACE(DEBUG, "USIM-API - res(f2) :%s",dump_octet_string(res_pP)); LOG_TRACE(DEBUG, "USIM-API - ck(f3) :%s",dump_octet_string(ck_pP)); LOG_TRACE(DEBUG, "USIM-API - ik(f4) :%s",dump_octet_string(ik_pP)); LOG_TRACE(DEBUG, "USIM-API - ak(f5) : %02X%02X%02X%02X%02X%02X", ak[0],ak[1],ak[2],ak[3],ak[4],ak[5]); /* Retrieve the sequence number SQN = (SQN ⊕ AK) ⊕ AK */ #define USIM_API_SQN_SIZE USIM_API_AK_SIZE u8 sqn[USIM_API_SQN_SIZE]; for (i = 0; i < USIM_API_SQN_SIZE; i++) { sqn[i] = autn_pP->value[i] ^ ak[i]; } LOG_TRACE(DEBUG, "USIM-API - Retrieved SQN %02X%02X%02X%02X%02X%02X", sqn[0],sqn[1],sqn[2],sqn[3],sqn[4],sqn[5]); /* Compute XMAC = f1K (SQN || RAND || AMF) */ #define USIM_API_XMAC_SIZE 8 u8 xmac[USIM_API_XMAC_SIZE]; f1(_usim_api_k, rand_pP->value, sqn, &autn_pP->value[USIM_API_SQN_SIZE], xmac); LOG_TRACE(DEBUG, "USIM-API - Computed XMAC %02X%02X%02X%02X%02X%02X%02X%02X", xmac[0],xmac[1],xmac[2],xmac[3], xmac[4],xmac[5],xmac[6],xmac[7]); /* Compare the XMAC with the MAC included in AUTN */ #define USIM_API_AMF_SIZE 2 if ( memcmp(xmac, &autn_pP->value[USIM_API_SQN_SIZE + USIM_API_AMF_SIZE], USIM_API_XMAC_SIZE) != 0 ) { LOG_TRACE(INFO, "USIM-API - Comparing the XMAC with the MAC included in AUTN Failed"); //LOG_FUNC_RETURN (RETURNerror); } else { LOG_TRACE(INFO, "USIM-API - Comparing the XMAC with the MAC included in AUTN Succeeded"); } /* Verify that the received sequence number SQN is in the correct range */ rc = _usim_api_check_sqn(*(uint32_t*)(sqn), sqn[USIM_API_SQN_SIZE - 1]); if (rc != RETURNok) { /* Synchronisation failure; compute the AUTS parameter */ /* Concealed value of the counter SQNms in the USIM: * Conc(SQNMS) = SQNMS ⊕ f5*K(RAND) */ f5star(_usim_api_k, rand_pP->value, ak); #define USIM_API_SQNMS_SIZE USIM_API_SQN_SIZE u8 sqn_ms[USIM_API_SQNMS_SIZE]; memset(sqn_ms, 0, USIM_API_SQNMS_SIZE); #define USIM_API_SQN_MS_SIZE 3 for (i = 0; i < USIM_API_SQN_MS_SIZE; i++) { #warning "LG:BUG HERE TODO" sqn_ms[USIM_API_SQNMS_SIZE - i] = ((uint8_t*)(_usim_api_data.sqn_ms))[USIM_API_SQN_MS_SIZE - i]; } u8 sqnms[USIM_API_SQNMS_SIZE]; for (i = 0; i < USIM_API_SQNMS_SIZE; i++) { sqnms[i] = sqn_ms[i] ^ ak[i]; } LOG_TRACE(DEBUG, "USIM-API - SQNms %02X%02X%02X%02X%02X%02X", sqnms[0],sqnms[1],sqnms[2],sqnms[3],sqnms[4],sqnms[5]); /* Synchronisation message authentication code: * MACS = f1*K(SQNMS || RAND || AMF) */ #define USIM_API_MACS_SIZE USIM_API_XMAC_SIZE u8 macs[USIM_API_MACS_SIZE]; f1star(_usim_api_k, rand_pP->value, sqn_ms, &rand_pP->value[USIM_API_SQN_SIZE], macs); LOG_TRACE(DEBUG, "USIM-API - MACS %02X%02X%02X%02X%02X%02X%02X%02X", macs[0],macs[1],macs[2],macs[3], macs[4],macs[5],macs[6],macs[7]); /* Synchronisation authentication token: * AUTS = Conc(SQNMS) || MACS */ memcpy(&auts_pP->value[0], sqnms, USIM_API_SQNMS_SIZE); memcpy(&auts_pP->value[USIM_API_SQNMS_SIZE], macs, USIM_API_MACS_SIZE); } LOG_FUNC_RETURN (RETURNok); }