mirror of https://github.com/PentHertz/srsLTE.git
perform initial attach with ESM info transfer
This commit is contained in:
parent
ff42fa0991
commit
4dc2951d59
|
@ -3792,6 +3792,8 @@ typedef struct{
|
|||
}LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT;
|
||||
// Functions
|
||||
LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_response_msg(LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp,
|
||||
uint8 sec_hdr_type,
|
||||
uint32 count,
|
||||
LIBLTE_BYTE_MSG_STRUCT *msg);
|
||||
LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg,
|
||||
LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp);
|
||||
|
|
|
@ -10041,10 +10041,19 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_request_msg(LIBLTE_BYTE_MSG_
|
|||
{
|
||||
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
||||
uint8 *msg_ptr = msg->msg;
|
||||
uint8 sec_hdr_type;
|
||||
|
||||
if(msg != NULL &&
|
||||
esm_info_req != NULL)
|
||||
{
|
||||
// Security Header Type
|
||||
sec_hdr_type = (msg->msg[0] & 0xF0) >> 4;
|
||||
if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS == sec_hdr_type) {
|
||||
msg_ptr++;
|
||||
} else{
|
||||
msg_ptr += 6;
|
||||
}
|
||||
|
||||
// EPS Bearer ID
|
||||
esm_info_req->eps_bearer_id = (*msg_ptr >> 4);
|
||||
msg_ptr++;
|
||||
|
@ -10072,6 +10081,8 @@ LIBLTE_ERROR_ENUM liblte_mme_unpack_esm_information_request_msg(LIBLTE_BYTE_MSG_
|
|||
Document Reference: 24.301 v10.2.0 Section 8.3.14
|
||||
*********************************************************************/
|
||||
LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_response_msg(LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp,
|
||||
uint8 sec_hdr_type,
|
||||
uint32 count,
|
||||
LIBLTE_BYTE_MSG_STRUCT *msg)
|
||||
{
|
||||
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
|
||||
|
@ -10080,6 +10091,20 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_response_msg(LIBLTE_MME_ESM_IN
|
|||
if(esm_info_resp != NULL &&
|
||||
msg != NULL)
|
||||
{
|
||||
if(LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS != sec_hdr_type)
|
||||
{
|
||||
// Protocol Discriminator and Security Header Type
|
||||
*msg_ptr = (sec_hdr_type << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
||||
msg_ptr++;
|
||||
|
||||
// MAC will be filled in later
|
||||
msg_ptr += 4;
|
||||
|
||||
// Sequence Number
|
||||
*msg_ptr = count & 0xFF;
|
||||
msg_ptr++;
|
||||
}
|
||||
|
||||
// Protocol Discriminator and EPS Bearer ID
|
||||
*msg_ptr = (esm_info_resp->eps_bearer_id << 4) | (LIBLTE_MME_PD_EPS_SESSION_MANAGEMENT);
|
||||
msg_ptr++;
|
||||
|
@ -10116,6 +10141,8 @@ LIBLTE_ERROR_ENUM liblte_mme_pack_esm_information_response_msg(LIBLTE_MME_ESM_IN
|
|||
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
||||
LIBLTE_ERROR_ENUM srslte_mme_unpack_esm_information_response_msg(LIBLTE_BYTE_MSG_STRUCT *msg,
|
||||
LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT *esm_info_resp)
|
||||
{
|
||||
|
|
|
@ -171,7 +171,8 @@ private:
|
|||
|
||||
// Senders
|
||||
void send_identity_response();
|
||||
void send_esm_information_response();
|
||||
void send_service_request();
|
||||
void send_esm_information_response(const uint8 proc_transaction_id);
|
||||
void send_authentication_response(const uint8_t* res, const size_t res_len);
|
||||
void send_authentication_failure(const uint8_t cause, const uint8_t* auth_fail_param);
|
||||
void gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <srslte/asn1/liblte_mme.h>
|
||||
#include "srslte/asn1/liblte_rrc.h"
|
||||
#include "srsue/hdr/upper/nas.h"
|
||||
#include "srslte/common/security.h"
|
||||
|
@ -51,7 +52,10 @@ nas::nas()
|
|||
ctxt.tx_count = 0;
|
||||
ctxt.cipher_algo = CIPHERING_ALGORITHM_ID_EEA0;
|
||||
ctxt.integ_algo = INTEGRITY_ALGORITHM_ID_EIA0;
|
||||
<<<<<<< HEAD
|
||||
plmn_is_selected = false;
|
||||
=======
|
||||
>>>>>>> perform initial attach with ESM info transfer
|
||||
}
|
||||
|
||||
void nas::init(usim_interface_nas *usim_,
|
||||
|
@ -353,7 +357,13 @@ void nas::write_pdu(uint32_t lcid, byte_buffer_t *pdu) {
|
|||
}
|
||||
|
||||
uint32_t nas::get_ul_count() {
|
||||
return ctxt.tx_count;
|
||||
// UL count for RRC key derivation depends on ESM information transfer procedure
|
||||
if (cfg.apn.empty()) {
|
||||
// No ESM info transfer has been sent
|
||||
return ctxt.tx_count - 1;
|
||||
} else {
|
||||
return ctxt.tx_count - 2;
|
||||
}
|
||||
}
|
||||
|
||||
bool nas::get_k_asme(uint8_t *k_asme_, uint32_t n) {
|
||||
|
@ -483,7 +493,11 @@ void nas::cipher_encrypt(byte_buffer_t *pdu)
|
|||
memcpy(&pdu->msg[6], &pdu_tmp.msg[6], pdu->N_bytes-6);
|
||||
break;
|
||||
default:
|
||||
<<<<<<< HEAD
|
||||
nas_log->error("Ciphering algorithm not known\n");
|
||||
=======
|
||||
nas_log->error("Ciphering algorithmus not known\n");
|
||||
>>>>>>> perform initial attach with ESM info transfer
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -517,7 +531,7 @@ void nas::cipher_decrypt(byte_buffer_t *pdu)
|
|||
memcpy(&pdu->msg[6], &tmp_pdu.msg[6], pdu->N_bytes-6);
|
||||
break;
|
||||
default:
|
||||
nas_log->error("Ciphering algorithmus not known");
|
||||
nas_log->error("Ciphering algorithmus not known\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -921,8 +935,15 @@ void nas::parse_service_reject(uint32_t lcid, byte_buffer_t *pdu) {
|
|||
}
|
||||
|
||||
void nas::parse_esm_information_request(uint32_t lcid, byte_buffer_t *pdu) {
|
||||
nas_log->error("TODO:parse_esm_information_request\n");
|
||||
LIBLTE_MME_ESM_INFORMATION_REQUEST_MSG_STRUCT esm_info_req;
|
||||
liblte_mme_unpack_esm_information_request_msg((LIBLTE_BYTE_MSG_STRUCT *)pdu, &esm_info_req);
|
||||
|
||||
nas_log->info("ESM information request received for beaser=%d, transaction_id=%d\n", esm_info_req.eps_bearer_id, esm_info_req.proc_transaction_id);
|
||||
ctxt.rx_count++;
|
||||
pool->deallocate(pdu);
|
||||
|
||||
// send response
|
||||
send_esm_information_response(esm_info_req.proc_transaction_id);
|
||||
}
|
||||
|
||||
void nas::parse_emm_information(uint32_t lcid, byte_buffer_t *pdu) {
|
||||
|
@ -1065,24 +1086,18 @@ void nas::gen_pdn_connectivity_request(LIBLTE_BYTE_MSG_STRUCT *msg) {
|
|||
pdn_con_req.proc_transaction_id = 0x01; // First transaction ID
|
||||
pdn_con_req.pdn_type = LIBLTE_MME_PDN_TYPE_IPV4;
|
||||
pdn_con_req.request_type = LIBLTE_MME_REQUEST_TYPE_INITIAL_REQUEST;
|
||||
pdn_con_req.apn_present = false;
|
||||
|
||||
// Set the optional flags
|
||||
pdn_con_req.esm_info_transfer_flag_present = false; //FIXME: Check if this is needed
|
||||
if (cfg.apn == "") {
|
||||
pdn_con_req.apn_present = false;
|
||||
pdn_con_req.esm_info_transfer_flag_present = false;
|
||||
} else {
|
||||
pdn_con_req.apn_present = true;
|
||||
LIBLTE_MME_ACCESS_POINT_NAME_STRUCT apn = {0};
|
||||
strncpy(apn.apn, cfg.apn.c_str(), LIBLTE_STRING_LEN);
|
||||
pdn_con_req.apn = apn;
|
||||
// request ESM info transfer is APN is specified
|
||||
pdn_con_req.esm_info_transfer_flag_present = true;
|
||||
pdn_con_req.esm_info_transfer_flag = LIBLTE_MME_ESM_INFO_TRANSFER_FLAG_REQUIRED;
|
||||
}
|
||||
|
||||
// Request DNS Server
|
||||
pdn_con_req.protocol_cnfg_opts_present = true;
|
||||
pdn_con_req.protocol_cnfg_opts.opt[0].id = LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_P_CSCF_IPV4_ADDRESS_REQUEST;
|
||||
pdn_con_req.protocol_cnfg_opts.opt[1].id = LIBLTE_MME_ADDITIONAL_PARAMETERS_UL_DNS_SERVER_IPV4_ADDRESS_REQUEST;
|
||||
pdn_con_req.protocol_cnfg_opts.N_opts = 2;
|
||||
|
||||
pdn_con_req.protocol_cnfg_opts_present = false;
|
||||
pdn_con_req.device_properties_present = false;
|
||||
|
||||
// Pack the message
|
||||
|
@ -1159,7 +1174,91 @@ void nas::send_authentication_failure(const uint8_t cause, const uint8_t* auth_f
|
|||
|
||||
void nas::send_identity_response() {}
|
||||
|
||||
void nas::send_esm_information_response() {}
|
||||
void nas::send_service_request() {
|
||||
byte_buffer_t *msg = pool_allocate;
|
||||
if (!msg) {
|
||||
nas_log->error("Fatal Error: Couldn't allocate PDU in send_service_request().\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Pack the service request message directly
|
||||
msg->msg[0] = (LIBLTE_MME_SECURITY_HDR_TYPE_SERVICE_REQUEST << 4) | (LIBLTE_MME_PD_EPS_MOBILITY_MANAGEMENT);
|
||||
msg->N_bytes++;
|
||||
msg->msg[1] = (ctxt.ksi & 0x07) << 5;
|
||||
msg->msg[1] |= ctxt.tx_count & 0x1F;
|
||||
msg->N_bytes++;
|
||||
|
||||
uint8_t mac[4];
|
||||
integrity_generate(&k_nas_int[16],
|
||||
ctxt.tx_count,
|
||||
SECURITY_DIRECTION_UPLINK,
|
||||
&msg->msg[0],
|
||||
2,
|
||||
&mac[0]);
|
||||
// Set the short MAC
|
||||
msg->msg[2] = mac[2];
|
||||
msg->N_bytes++;
|
||||
msg->msg[3] = mac[3];
|
||||
msg->N_bytes++;
|
||||
|
||||
if(pcap != NULL) {
|
||||
pcap->write_nas(msg->msg, msg->N_bytes);
|
||||
}
|
||||
|
||||
nas_log->info("Sending service request\n");
|
||||
rrc->write_sdu(cfg.lcid, msg);
|
||||
ctxt.tx_count++;
|
||||
}
|
||||
|
||||
void nas::send_esm_information_response(const uint8 proc_transaction_id) {
|
||||
LIBLTE_MME_ESM_INFORMATION_RESPONSE_MSG_STRUCT esm_info_resp;
|
||||
esm_info_resp.proc_transaction_id = proc_transaction_id;
|
||||
esm_info_resp.eps_bearer_id = 0; // respone shall always have no bearer assigned
|
||||
|
||||
if (cfg.apn == "") {
|
||||
esm_info_resp.apn_present = false;
|
||||
} else {
|
||||
esm_info_resp.apn_present = true;
|
||||
esm_info_resp.apn.apn = cfg.apn;
|
||||
}
|
||||
esm_info_resp.protocol_cnfg_opts_present = false;
|
||||
|
||||
byte_buffer_t *pdu = pool_allocate;
|
||||
if (!pdu) {
|
||||
nas_log->error("Fatal Error: Couldn't allocate PDU in send_attach_request().\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (liblte_mme_pack_esm_information_response_msg(&esm_info_resp,
|
||||
LIBLTE_MME_SECURITY_HDR_TYPE_INTEGRITY_AND_CIPHERED,
|
||||
ctxt.tx_count,
|
||||
(LIBLTE_BYTE_MSG_STRUCT *)pdu)) {
|
||||
nas_log->error("Error packing ESM information response.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(pcap != NULL) {
|
||||
pcap->write_nas(pdu->msg, pdu->N_bytes);
|
||||
}
|
||||
|
||||
cipher_encrypt(pdu);
|
||||
if (pdu->N_bytes > 5) {
|
||||
integrity_generate(&k_nas_int[16],
|
||||
ctxt.tx_count,
|
||||
SECURITY_DIRECTION_UPLINK,
|
||||
&pdu->msg[5],
|
||||
pdu->N_bytes - 5,
|
||||
&pdu->msg[1]);
|
||||
} else {
|
||||
nas_log->error("Invalid PDU size %d\n", pdu->N_bytes);
|
||||
return;
|
||||
}
|
||||
|
||||
nas_log->info_hex(pdu->msg, pdu->N_bytes, "Sending ESM information response\n");
|
||||
rrc->write_sdu(cfg.lcid, pdu);
|
||||
|
||||
ctxt.tx_count++;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
@ -1947,7 +1947,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu) {
|
|||
// Generate AS security keys
|
||||
uint8_t k_asme[32];
|
||||
nas->get_k_asme(k_asme, 32);
|
||||
usim->generate_as_keys(k_asme, nas->get_ul_count()-1, k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo);
|
||||
usim->generate_as_keys(k_asme, nas->get_ul_count(), k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo);
|
||||
rrc_log->debug_hex(k_rrc_enc, 32, "RRC encryption key - k_rrc_enc");
|
||||
rrc_log->debug_hex(k_rrc_int, 32, "RRC integrity key - k_rrc_int");
|
||||
rrc_log->debug_hex(k_up_enc, 32, "UP encryption key - k_up_enc");
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include <assert.h>
|
||||
#include <srsue/hdr/upper/usim_base.h>
|
||||
#include "srsue/hdr/upper/usim.h"
|
||||
#include "srsue/hdr/upper/pcsc_usim.h"
|
||||
#include "srsue/hdr/upper/nas.h"
|
||||
#include "srslte/upper/rlc.h"
|
||||
#include "srsue/hdr/upper/rrc.h"
|
||||
|
@ -61,6 +60,8 @@ uint8_t attach_accept_pdu[] = { 0x27, 0x0f, 0x4f, 0xb3, 0xef, 0x01, 0x07, 0x42,
|
|||
0x80, 0x50, 0x0b, 0xf6, 0x00, 0xf1, 0x10, 0x80, 0x01, 0x01,
|
||||
0x35, 0x16, 0x6d, 0xbc, 0x64, 0x01, 0x00 };
|
||||
|
||||
uint8_t esm_info_req_pdu[] = { 0x27, 0x1d, 0xbf, 0x7e, 0x05, 0x01, 0x02, 0x5a, 0xd9 };
|
||||
|
||||
uint16 mcc = 61441;
|
||||
uint16 mnc = 65281;
|
||||
|
||||
|
@ -204,9 +205,9 @@ int mme_attach_request_test()
|
|||
|
||||
rrc_dummy rrc_dummy;
|
||||
gw_dummy gw;
|
||||
srsue::pcsc_usim usim;
|
||||
srsue::usim usim;
|
||||
usim_args_t args;
|
||||
args.mode = "pcsc";
|
||||
args.mode = "soft";
|
||||
args.algo = "xor";
|
||||
args.imei = "353490069873319";
|
||||
args.imsi = "001010123456789";
|
||||
|
@ -215,6 +216,7 @@ int mme_attach_request_test()
|
|||
usim.init(&args, &usim_log);
|
||||
|
||||
srslte_nas_config_t nas_cfg;
|
||||
nas_cfg.apn = "test123";
|
||||
srsue::nas nas;
|
||||
nas.init(&usim, &rrc_dummy, &gw, &nas_log, nas_cfg);
|
||||
|
||||
|
@ -239,6 +241,61 @@ int mme_attach_request_test()
|
|||
}
|
||||
|
||||
|
||||
|
||||
int esm_info_request_test()
|
||||
{
|
||||
int ret = SRSLTE_ERROR;
|
||||
srslte::log_filter nas_log("NAS");
|
||||
srslte::log_filter rrc_log("RRC");
|
||||
srslte::log_filter mac_log("MAC");
|
||||
srslte::log_filter usim_log("USIM");
|
||||
|
||||
nas_log.set_level(srslte::LOG_LEVEL_DEBUG);
|
||||
rrc_log.set_level(srslte::LOG_LEVEL_DEBUG);
|
||||
nas_log.set_hex_limit(100000);
|
||||
rrc_log.set_hex_limit(100000);
|
||||
|
||||
rrc_dummy rrc_dummy;
|
||||
gw_dummy gw;
|
||||
|
||||
usim_args_t args;
|
||||
args.algo = "xor";
|
||||
args.imei = "353490069873319";
|
||||
args.imsi = "001010123456789";
|
||||
args.k = "00112233445566778899aabbccddeeff";
|
||||
args.op = "63BFA50EE6523365FF14C1F45F88737D";
|
||||
|
||||
// init USIM
|
||||
srsue::usim usim;
|
||||
bool net_valid;
|
||||
uint8_t res[16];
|
||||
usim.init(&args, &usim_log);
|
||||
|
||||
srslte::byte_buffer_pool *pool;
|
||||
pool = byte_buffer_pool::get_instance();
|
||||
|
||||
srsue::nas nas;
|
||||
srslte_nas_config_t cfg;
|
||||
cfg.apn = "srslte";
|
||||
nas.init(&usim, &rrc_dummy, &gw, &nas_log, cfg);
|
||||
|
||||
// push ESM info request PDU to NAS to generate response
|
||||
byte_buffer_t* tmp = pool->allocate();
|
||||
memcpy(tmp->msg, esm_info_req_pdu, sizeof(esm_info_req_pdu));
|
||||
tmp->N_bytes = sizeof(esm_info_req_pdu);
|
||||
nas.write_pdu(LCID, tmp);
|
||||
|
||||
// check length of generated NAS SDU
|
||||
if (rrc_dummy.get_last_sdu_len() > 3) {
|
||||
ret = SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
pool->cleanup();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (security_command_test()) {
|
||||
|
@ -251,5 +308,10 @@ int main(int argc, char **argv)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (esm_info_request_test()) {
|
||||
printf("ESM info request test failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue