srsue/extnas: handle (U)SIM GenAuthResp.Request

This commit is contained in:
Vadim Yanitskiy 2020-11-03 18:06:36 +07:00
parent 27344af7f0
commit b594b15e79
2 changed files with 110 additions and 0 deletions

View File

@ -90,6 +90,10 @@ private:
void handle_rrctl_data(rrctl::proto::msg_disc disc, const uint8_t* msg, size_t len);
void handle_rrctl_param(rrctl::proto::msg_disc disc, const uint8_t* msg, size_t len);
void handle_rrctl_ext_usim(const uint8_t* msg, size_t len);
void handle_usim_gen_auth_resp_req(const struct rrctl::proto::ext_usim_msg* msg, size_t len);
void handle_usim_gen_nas_keys_req(const struct rrctl::proto::ext_usim_msg* msg, size_t len);
void rrctl_send_confirm(rrctl::proto::msg_type type);
void rrctl_send_error(rrctl::proto::msg_type type);
};

View File

@ -85,6 +85,8 @@ void nas_ext::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interf
break;
case rrctl::proto::RRCTL_SEC_MODE:
case rrctl::proto::RRCTL_EXT_USIM:
handle_rrctl_ext_usim(payload, length);
break;
case rrctl::proto::RRCTL_CONN_RELEASE:
default:
nas_log->warning("%s is not handled\n", desc.c_str());
@ -213,6 +215,110 @@ void nas_ext::handle_rrctl_param(rrctl::proto::msg_disc disc, const uint8_t* msg
}
}
void nas_ext::handle_rrctl_ext_usim(const uint8_t* _msg, size_t len)
{
enum rrctl::proto::ext_usim_msg_type msg_type;
const struct rrctl::proto::ext_usim_msg* msg;
std::string msg_desc;
if (len < 4) { /* XXX: type + padding */
nas_log->error("Received too short (U)SIM specific message (len=%zu)\n", len);
rrctl_send_error(rrctl::proto::RRCTL_EXT_USIM);
return;
}
/* Skip the header */
len -= 4;
msg = reinterpret_cast<const struct rrctl::proto::ext_usim_msg*> (_msg);
msg_type = static_cast<rrctl::proto::ext_usim_msg_type> (msg->type);
switch (msg_type) {
case rrctl::proto::EXT_USIM_GEN_AUTH_RESP:
handle_usim_gen_auth_resp_req(msg, len);
break;
case rrctl::proto::EXT_USIM_RAW_APDU:
case rrctl::proto::EXT_USIM_READ_FILE:
case rrctl::proto::EXT_USIM_UPDATE_FILE:
case rrctl::proto::EXT_USIM_RESERVED:
default:
nas_log->warning("(U)SIM specific message 0x%02x is not handled\n", msg->type);
}
}
void nas_ext::handle_usim_gen_auth_resp_req(const struct rrctl::proto::ext_usim_msg* msg, size_t len)
{
const struct rrctl::proto::ext_usim_gen_auth_resp_req* req;
struct rrctl::proto::ext_usim_gen_auth_resp_rsp* rsp;
struct rrctl::proto::ext_usim_msg* rsp_msg;
std::pair<uint16_t, uint16_t> mcc_mnc;
struct rrctl::proto::msg_hdr* hdr;
srslte::byte_buffer_t pdu;
/* Allocate the response message in advance */
hdr = rrctl::codec::enc_hdr(pdu, rrctl::proto::RRCTL_EXT_USIM, rrctl::proto::RRCTL_CNF, 4);
rsp_msg = reinterpret_cast<struct rrctl::proto::ext_usim_msg*> (&pdu.msg[pdu.N_bytes]);
rsp_msg->type = msg->type;
pdu.N_bytes += 4;
if (len < sizeof(*req)) {
nas_log->error("Received too short (U)SIM GenAuthResp.req (len=%zu)\n", len);
hdr->disc = (uint8_t) rrctl::proto::RRCTL_ERR;
iface->write(pdu);
return;
}
rsp = &rsp_msg->u.gen_auth_resp_rsp;
req = &msg->u.gen_auth_resp_req;
// Parse PLMN ID
try {
/* HACK: generalize this function */
rrctl::codec::dec_plmn_select_req(mcc_mnc, &req->mcc[0], len);
} catch (const rrctl::codec::error& e) {
nas_log->warning("Failed to parse MCC/MNC: %s\n", e.what());
hdr->disc = (uint8_t) rrctl::proto::RRCTL_ERR;
iface->write(pdu);
return;
}
uint8_t k_asme[32];
uint8_t res[16];
int res_len;
/* NOTE: this is a blocking call => no other RRCTL messages can be processed in parallel?
* FIXME: the authors of srsUE apparently are not aware of 'const', so we have to cast. */
auth_result_t auth_res = usim->generate_authentication_response((uint8_t*) &req->rand[0],
(uint8_t*) &req->autn[0],
mcc_mnc.first, mcc_mnc.second,
&res[0], &res_len, &k_asme[0]);
switch (auth_res) {
case AUTH_OK:
nas_log->info("Authentication vector has been generated successfully\n");
pdu.N_bytes += sizeof(*rsp);
pdu.append_bytes(&k_asme[0], sizeof(k_asme));
pdu.append_bytes(&res[0], res_len);
rsp->res_len = (uint8_t) res_len;
break;
case AUTH_SYNCH_FAILURE:
nas_log->warning("Synchronization is required to generate an authentication vector\n");
pdu.N_bytes += sizeof(*rsp);
pdu.append_bytes(&res[0], res_len);
rsp->res_len = (uint8_t) res_len;
rsp->out_of_sync = true;
break;
case AUTH_FAILED:
default:
nas_log->warning("Could not generate an authentication vector\n");
hdr->disc = (uint8_t) rrctl::proto::RRCTL_ERR;
}
hdr->len = htons(pdu.N_bytes - sizeof(*hdr));
iface->write(pdu);
}
void nas_ext::get_metrics(nas_metrics_t* m)
{
nas_metrics_t metrics = {};