static int eap_sim_get_challenge(eap_handler_t *handler, VALUE_PAIR *vps, int idx, eap_sim_state_t *ess) { REQUEST *request = handler->request; VALUE_PAIR *vp, *ki, *algo_version; rad_assert(idx >= 0 && idx < 3); /* * Generate a new RAND value, and derive Kc and SRES from Ki */ ki = pairfind(vps, PW_EAP_SIM_KI, 0, TAG_ANY); if (ki) { int i; /* * Check to see if have a Ki for the IMSI, this allows us to generate the rest * of the triplets. */ algo_version = pairfind(vps, PW_EAP_SIM_ALGO_VERSION, 0, TAG_ANY); if (!algo_version) { REDEBUG("Found Ki, but missing EAP-Sim-Algo-Version"); return 0; } for (i = 0; i < EAPSIM_RAND_SIZE; i++) { ess->keys.rand[idx][i] = fr_rand(); } switch (algo_version->vp_integer) { case 1: comp128v1(ess->keys.sres[idx], ess->keys.Kc[idx], ki->vp_octets, ess->keys.rand[idx]); break; case 2: comp128v23(ess->keys.sres[idx], ess->keys.Kc[idx], ki->vp_octets, ess->keys.rand[idx], true); break; case 3: comp128v23(ess->keys.sres[idx], ess->keys.Kc[idx], ki->vp_octets, ess->keys.rand[idx], false); break; case 4: REDEBUG("Comp128-4 algorithm is not supported as details have not yet been published. " "If you have details of this algorithm please contact the FreeRADIUS " "maintainers"); return 0; default: REDEBUG("Unknown/unsupported algorithm Comp128-%i", algo_version->vp_integer); } if (RDEBUG_ENABLED2) { char buffer[33]; /* 32 hexits (16 bytes) + 1 */ char *p; RDEBUG2("Generated following triplets for round %i:", idx); p = buffer; for (i = 0; i < EAPSIM_RAND_SIZE; i++) { p += sprintf(p, "%02x", ess->keys.rand[idx][i]); } RDEBUG2("\tRAND : 0x%s", buffer); p = buffer; for (i = 0; i < EAPSIM_SRES_SIZE; i++) { p += sprintf(p, "%02x", ess->keys.sres[idx][i]); } RDEBUG2("\tSRES : 0x%s", buffer); p = buffer; for (i = 0; i < EAPSIM_KC_SIZE; i++) { p += sprintf(p, "%02x", ess->keys.Kc[idx][i]); } RDEBUG2("\tKc : 0x%s", buffer); } return 1; } /* * Use known RAND, SRES, and Kc values, these may of been pulled in from an AuC, * or created by sending challenges to the SIM directly. */ vp = pairfind(vps, PW_EAP_SIM_RAND1 + idx, 0, TAG_ANY); if (!vp) { /* bad, we can't find stuff! */ REDEBUG("control:EAP-SIM-RAND%i not found", idx + 1); return 0; } if (vp->length != EAPSIM_RAND_SIZE) { REDEBUG("control:EAP-SIM-RAND%i is not " STRINGIFY(EAPSIM_RAND_SIZE) " bytes, got %zu bytes", idx + 1, vp->length); return 0; } memcpy(ess->keys.rand[idx], vp->vp_octets, EAPSIM_RAND_SIZE); vp = pairfind(vps, PW_EAP_SIM_SRES1 + idx, 0, TAG_ANY); if (!vp) { /* bad, we can't find stuff! */ REDEBUG("control:EAP-SIM-SRES%i not found", idx + 1); return 0; } if (vp->length != EAPSIM_SRES_SIZE) { REDEBUG("control:EAP-SIM-SRES%i is not " STRINGIFY(EAPSIM_SRES_SIZE) " bytes, got %zu bytes", idx + 1, vp->length); return 0; } memcpy(ess->keys.sres[idx], vp->vp_octets, EAPSIM_SRES_SIZE); vp = pairfind(vps, PW_EAP_SIM_KC1 + idx, 0, TAG_ANY); if (!vp) { /* bad, we can't find stuff! */ REDEBUG("control:EAP-SIM-Kc%i not found", idx + 1); return 0; } if (vp->length != EAPSIM_KC_SIZE) { REDEBUG("control:EAP-SIM-Kc%i is not 8 bytes, got %zu bytes", idx + 1, vp->length); return 0; } memcpy(ess->keys.Kc[idx], vp->vp_octets, EAPSIM_KC_SIZE); if (vp->length != EAPSIM_KC_SIZE) { REDEBUG("control:EAP-SIM-Kc%i is not " STRINGIFY(EAPSIM_KC_SIZE) " bytes, got %zu bytes", idx + 1, vp->length); return 0; } memcpy(ess->keys.Kc[idx], vp->vp_strvalue, EAPSIM_KC_SIZE); return 1; }
static int vector_gsm_from_ki(eap_session_t *eap_session, VALUE_PAIR *vps, int idx, fr_sim_keys_t *keys) { REQUEST *request = eap_session->request; VALUE_PAIR *ki_vp, *version_vp; uint8_t opc_buff[MILENAGE_OPC_SIZE]; uint8_t const *opc_p; uint32_t version; int i; /* * Generate a new RAND value, and derive Kc and SRES from Ki */ ki_vp = fr_pair_find_by_da(vps, attr_sim_ki, TAG_ANY); if (!ki_vp) { RDEBUG3("No &control:%sfound, not generating triplets locally", attr_sim_ki->name); return 1; } else if (ki_vp->vp_length != MILENAGE_KI_SIZE) { REDEBUG("&control:%s has incorrect length, expected 16 bytes got %zu bytes", attr_sim_ki->name, ki_vp->vp_length); return -1; } /* * Check to see if have a Ki for the IMSI, this allows us to generate the rest * of the triplets. */ version_vp = fr_pair_find_by_da(vps, attr_sim_algo_version, TAG_ANY); if (!version_vp) { if (vector_opc_from_op(request, &opc_p, opc_buff, vps, ki_vp->vp_octets) < 0) return -1; version = opc_p ? 4 : 3; /* * Version we explicitly specified, see if we can find the prerequisite * attributes. */ } else { version = version_vp->vp_uint32; if (version == 4) { if (vector_opc_from_op(request, &opc_p, opc_buff, vps, ki_vp->vp_octets) < 0) return -1; if (!opc_p) { RPEDEBUG2("No &control:%s or &control:%s found, " "can't run Milenage (COMP128-4)", attr_sim_op->name, attr_sim_opc->name); return -1; } } } for (i = 0; i < SIM_VECTOR_GSM_RAND_SIZE; i += sizeof(uint32_t)) { uint32_t rand = fr_rand(); memcpy(&keys->gsm.vector[idx].rand[i], &rand, sizeof(rand)); } switch (version) { case 1: comp128v1(keys->gsm.vector[idx].sres, keys->gsm.vector[idx].kc, ki_vp->vp_octets, keys->gsm.vector[idx].rand); break; case 2: comp128v23(keys->gsm.vector[idx].sres, keys->gsm.vector[idx].kc, ki_vp->vp_octets, keys->gsm.vector[idx].rand, true); break; case 3: comp128v23(keys->gsm.vector[idx].sres, keys->gsm.vector[idx].kc, ki_vp->vp_octets, keys->gsm.vector[idx].rand, false); break; case 4: if (milenage_gsm_generate(keys->gsm.vector[idx].sres, keys->gsm.vector[idx].kc, opc_p, ki_vp->vp_octets, keys->gsm.vector[idx].rand) < 0) { RPEDEBUG2("Failed deriving GSM triplet"); return -1; } return 0; default: REDEBUG("Unknown/unsupported algorithm %i", version); return -1; } return 0; }