/**************************************************************************** ** ** ** Name: emm_as_set_security_data() ** ** ** ** Description: Setup security data according to the given EPS security ** ** context when data transfer to lower layers is requested ** ** ** ** Inputs: args: EPS security context currently in use ** ** is_new: Indicates whether a new security context ** ** has just been taken into use ** ** is_ciphered: Indicates whether the NAS message has to ** ** be sent ciphered ** ** Others: None ** ** ** ** Outputs: data: EPS NAS security data to be setup ** ** Return: None ** ** Others: None ** ** ** ***************************************************************************/ void emm_as_set_security_data(emm_as_security_data_t *data, const void *args, int is_new, int is_ciphered) { LOG_FUNC_IN; const emm_security_context_t *context = (emm_security_context_t *)(args); memset(data, 0, sizeof(emm_as_security_data_t)); if ( context && (context->type != EMM_KSI_NOT_AVAILABLE) ) { /* 3GPP TS 24.301, sections 5.4.3.3 and 5.4.3.4 * Once a valid EPS security context exists and has been taken * into use, UE and MME shall cipher and integrity protect all * NAS signalling messages with the selected NAS ciphering and * NAS integrity algorithms */ LOG_TRACE(INFO, "EPS security context exists is new %u KSI %u SQN %u count %u", is_new, context->eksi, context->ul_count.seq_num, *(uint32_t *)(&context->ul_count)); LOG_TRACE(INFO, "knas_int %s",dump_octet_string(&context->knas_int)); LOG_TRACE(INFO, "knas_enc %s",dump_octet_string(&context->knas_enc)); LOG_TRACE(INFO, "kasme %s",dump_octet_string(&context->kasme)); data->is_new = is_new; data->ksi = context->eksi; data->sqn = context->ul_count.seq_num; // LG data->count = *(uint32_t *)(&context->ul_count); data->count = 0x00000000 | (context->ul_count.overflow << 8 ) | context->ul_count.seq_num; /* NAS integrity and cyphering keys may not be available if the * current security context is a partial EPS security context * and not a full native EPS security context */ data->k_int = &context->knas_int; if (is_ciphered) { /* 3GPP TS 24.301, sections 4.4.5 * When the UE establishes a new NAS signalling connection, * it shall send initial NAS messages integrity protected * and unciphered */ /* 3GPP TS 24.301, section 5.4.3.2 * The MME shall send the SECURITY MODE COMMAND message integrity * protected and unciphered */ LOG_TRACE(WARNING, "EPS security context exists knas_enc"); data->k_enc = &context->knas_enc; } } else { LOG_TRACE(WARNING, "EMM_AS_NO_KEY_AVAILABLE"); /* No valid EPS security context exists */ data->ksi = EMM_AS_NO_KEY_AVAILABLE; } LOG_FUNC_OUT; }
/**************************************************************************** ** ** ** 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); }
/**************************************************************************** ** ** ** Name: esm_send_activate_default_eps_bearer_context_request() ** ** ** ** Description: Builds Activate Default EPS Bearer Context Request ** ** message ** ** ** ** The activate default EPS bearer context request message ** ** is sent by the network to the UE to request activation of ** ** a default EPS bearer context. ** ** ** ** Inputs: pti: Procedure transaction identity ** ** ebi: EPS bearer identity ** ** qos: Subscribed EPS quality of service ** ** apn: Access Point Name in used ** ** pdn_addr: PDN IPv4 address and/or IPv6 suffix ** ** esm_cause: ESM cause code ** ** Others: None ** ** ** ** Outputs: msg: The ESM message to be sent ** ** Return: RETURNok, RETURNerror ** ** Others: None ** ** ** ***************************************************************************/ int esm_send_activate_default_eps_bearer_context_request ( int pti, int ebi, activate_default_eps_bearer_context_request_msg * msg, const OctetString * apn, const ProtocolConfigurationOptions * pco, int pdn_type, const OctetString * pdn_addr, const EpsQualityOfService * qos, int esm_cause) { LOG_FUNC_IN; /* * Mandatory - ESM message header */ msg->protocoldiscriminator = EPS_SESSION_MANAGEMENT_MESSAGE; msg->epsbeareridentity = ebi; msg->messagetype = ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST; msg->proceduretransactionidentity = pti; /* * Mandatory - EPS QoS */ msg->epsqos = *qos; LOG_TRACE (INFO, "ESM-SAP - epsqos qci: %u", qos->qci); if (qos->bitRatesPresent) { LOG_TRACE (INFO, "ESM-SAP - epsqos maxBitRateForUL: %u", qos->bitRates.maxBitRateForUL); LOG_TRACE (INFO, "ESM-SAP - epsqos maxBitRateForDL: %u", qos->bitRates.maxBitRateForDL); LOG_TRACE (INFO, "ESM-SAP - epsqos guarBitRateForUL: %u", qos->bitRates.guarBitRateForUL); LOG_TRACE (INFO, "ESM-SAP - epsqos guarBitRateForDL: %u", qos->bitRates.guarBitRateForDL); } else { LOG_TRACE (INFO, "ESM-SAP - epsqos no bit rates defined"); } if (qos->bitRatesExtPresent) { LOG_TRACE (INFO, "ESM-SAP - epsqos maxBitRateForUL Ext: %u", qos->bitRatesExt.maxBitRateForUL); LOG_TRACE (INFO, "ESM-SAP - epsqos maxBitRateForDL Ext: %u", qos->bitRatesExt.maxBitRateForDL); LOG_TRACE (INFO, "ESM-SAP - epsqos guarBitRateForUL Ext: %u", qos->bitRatesExt.guarBitRateForUL); LOG_TRACE (INFO, "ESM-SAP - epsqos guarBitRateForDL Ext: %u", qos->bitRatesExt.guarBitRateForDL); } else { LOG_TRACE (INFO, "ESM-SAP - epsqos no bit rates ext defined"); } if ((apn == NULL) || ((apn != NULL) && (apn->value == NULL))) { LOG_TRACE (WARNING, "ESM-SAP - apn is NULL!"); } LOG_TRACE (INFO, "ESM-SAP - apn is %s", apn->value); /* * Mandatory - Access Point Name */ msg->accesspointname.accesspointnamevalue = *apn; /* * Mandatory - PDN address */ LOG_TRACE (INFO, "ESM-SAP - pdn_type is %u", pdn_type); msg->pdnaddress.pdntypevalue = pdn_type; LOG_TRACE (INFO, "ESM-SAP - pdn_addr is %u", dump_octet_string (pdn_addr)); msg->pdnaddress.pdnaddressinformation = *pdn_addr; /* * Optional - ESM cause code */ msg->presencemask = 0; if (esm_cause != ESM_CAUSE_SUCCESS) { msg->presencemask |= ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_ESM_CAUSE_PRESENT; msg->esmcause = esm_cause; } if (pco != NULL) { msg->presencemask |= ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_PROTOCOL_CONFIGURATION_OPTIONS_PRESENT; msg->protocolconfigurationoptions = *pco; } #warning "TEST LG FORCE APN-AMBR" LOG_TRACE (INFO, "ESM-SAP - FORCE APN-AMBR"); msg->presencemask |= ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST_APNAMBR_PRESENT; msg->apnambr.apnambrfordownlink = 0xfe; // (8640kbps) msg->apnambr.apnambrforuplink = 0xfe; // (8640kbps) msg->apnambr.apnambrfordownlink_extended = 0xde; // (200Mbps) msg->apnambr.apnambrforuplink_extended = 0x9e; // (100Mbps) msg->apnambr.apnambrfordownlink_extended2 = 0; msg->apnambr.apnambrforuplink_extended2 = 0; msg->apnambr.extensions = 0 | APN_AGGREGATE_MAXIMUM_BIT_RATE_MAXIMUM_EXTENSION_PRESENT; LOG_TRACE (INFO, "ESM-SAP - Send Activate Default EPS Bearer Context " "Request message (pti=%d, ebi=%d)", msg->proceduretransactionidentity, msg->epsbeareridentity); LOG_FUNC_RETURN (RETURNok); }