security-mode complete

This commit is contained in:
Sukchan Lee 2017-03-07 14:47:17 +09:00
parent e7c9dbfc4d
commit 48bc61d06a
9 changed files with 263 additions and 121 deletions

View File

@ -690,38 +690,58 @@ CORE_DECLARE(c_int32_t) nas_encode_tracking_area_identity_list(
* M LV 3-14 */
typedef struct _nas_ue_network_capability_t {
c_uint8_t length;
ED8(c_uint8_t eea0:1;,
c_uint8_t eea1:1;,
c_uint8_t eea2:1;,
c_uint8_t eea3:1;,
c_uint8_t eea4:1;,
c_uint8_t eea5:1;,
c_uint8_t eea6:1;,
c_uint8_t eea7:1;)
ED8(c_uint8_t eia0:1;,
c_uint8_t eia1:1;,
c_uint8_t eia2:1;,
c_uint8_t eia3:1;,
c_uint8_t eia4:1;,
c_uint8_t eia5:1;,
c_uint8_t eia6:1;,
c_uint8_t eia7:1;)
ED8(c_uint8_t uea0:1;,
c_uint8_t uea1:1;,
c_uint8_t uea2:1;,
c_uint8_t uea3:1;,
c_uint8_t uea4:1;,
c_uint8_t uea5:1;,
c_uint8_t uea6:1;,
c_uint8_t uea7:1;)
ED8(c_uint8_t ucs2:1;,
c_uint8_t uia1:1;,
c_uint8_t uia2:1;,
c_uint8_t uia3:1;,
c_uint8_t uia4:1;,
c_uint8_t uia5:1;,
c_uint8_t uia6:1;,
c_uint8_t uia7:1;)
union {
struct {
ED8(c_uint8_t eea0:1;,
c_uint8_t eea1:1;,
c_uint8_t eea2:1;,
c_uint8_t eea3:1;,
c_uint8_t eea4:1;,
c_uint8_t eea5:1;,
c_uint8_t eea6:1;,
c_uint8_t eea7:1;)
};
c_uint8_t eea;
};
union {
struct {
ED8(c_uint8_t eia0:1;,
c_uint8_t eia1:1;,
c_uint8_t eia2:1;,
c_uint8_t eia3:1;,
c_uint8_t eia4:1;,
c_uint8_t eia5:1;,
c_uint8_t eia6:1;,
c_uint8_t eia7:1;)
};
c_uint8_t eia;
};
union {
struct {
ED8(c_uint8_t uea0:1;,
c_uint8_t uea1:1;,
c_uint8_t uea2:1;,
c_uint8_t uea3:1;,
c_uint8_t uea4:1;,
c_uint8_t uea5:1;,
c_uint8_t uea6:1;,
c_uint8_t uea7:1;)
};
c_uint8_t uea;
};
union {
struct {
ED8(c_uint8_t ucs2:1;,
c_uint8_t uia1:1;,
c_uint8_t uia2:1;,
c_uint8_t uia3:1;,
c_uint8_t uia4:1;,
c_uint8_t uia5:1;,
c_uint8_t uia6:1;,
c_uint8_t uia7:1;)
};
c_uint8_t uia;
};
ED8(c_uint8_t prose_dd:1;,
c_uint8_t prose:1;,
c_uint8_t h_245_ash:1;,
@ -749,46 +769,71 @@ CORE_DECLARE(c_int32_t) nas_decode_ue_network_capability(
* M LV 3-6 */
typedef struct _nas_ue_security_capability_t {
c_uint8_t length;
ED8(c_uint8_t eea0:1;,
c_uint8_t eea1:1;,
c_uint8_t eea2:1;,
c_uint8_t eea3:1;,
c_uint8_t eea4:1;,
c_uint8_t eea5:1;,
c_uint8_t eea6:1;,
c_uint8_t eea7:1;)
ED8(c_uint8_t eia0:1;,
c_uint8_t eia1:1;,
c_uint8_t eia2:1;,
c_uint8_t eia3:1;,
c_uint8_t eia4:1;,
c_uint8_t eia5:1;,
c_uint8_t eia6:1;,
c_uint8_t eia7:1;)
ED8(c_uint8_t uea0:1;,
c_uint8_t uea1:1;,
c_uint8_t uea2:1;,
c_uint8_t uea3:1;,
c_uint8_t uea4:1;,
c_uint8_t uea5:1;,
c_uint8_t uea6:1;,
c_uint8_t uea7:1;)
ED8(c_uint8_t spare1:1;,
c_uint8_t uia1:1;,
c_uint8_t uia2:1;,
c_uint8_t uia3:1;,
c_uint8_t uia4:1;,
c_uint8_t uia5:1;,
c_uint8_t uia6:1;,
c_uint8_t uia7:1;)
ED8(c_uint8_t spare2:1;,
c_uint8_t gea1:1;,
c_uint8_t gea2:1;,
c_uint8_t gea3:1;,
c_uint8_t gea4:1;,
c_uint8_t gea5:1;,
c_uint8_t gea6:1;,
c_uint8_t gea7:1;)
union {
struct {
ED8(c_uint8_t eea0:1;,
c_uint8_t eea1:1;,
c_uint8_t eea2:1;,
c_uint8_t eea3:1;,
c_uint8_t eea4:1;,
c_uint8_t eea5:1;,
c_uint8_t eea6:1;,
c_uint8_t eea7:1;)
};
c_uint8_t eea;
};
union {
struct {
ED8(c_uint8_t eia0:1;,
c_uint8_t eia1:1;,
c_uint8_t eia2:1;,
c_uint8_t eia3:1;,
c_uint8_t eia4:1;,
c_uint8_t eia5:1;,
c_uint8_t eia6:1;,
c_uint8_t eia7:1;)
};
c_uint8_t eia;
};
union {
struct {
ED8(c_uint8_t uea0:1;,
c_uint8_t uea1:1;,
c_uint8_t uea2:1;,
c_uint8_t uea3:1;,
c_uint8_t uea4:1;,
c_uint8_t uea5:1;,
c_uint8_t uea6:1;,
c_uint8_t uea7:1;)
};
c_uint8_t uea;
};
union {
struct {
ED8(c_uint8_t spare1:1;,
c_uint8_t uia1:1;,
c_uint8_t uia2:1;,
c_uint8_t uia3:1;,
c_uint8_t uia4:1;,
c_uint8_t uia5:1;,
c_uint8_t uia6:1;,
c_uint8_t uia7:1;)
};
c_uint8_t uia;
};
union {
struct {
ED8(c_uint8_t spare2:1;,
c_uint8_t gea1:1;,
c_uint8_t gea2:1;,
c_uint8_t gea3:1;,
c_uint8_t gea4:1;,
c_uint8_t gea5:1;,
c_uint8_t gea6:1;,
c_uint8_t gea7:1;)
};
c_uint8_t gea;
};
} __attribute__ ((packed)) nas_ue_security_capability_t;
CORE_DECLARE(c_int32_t) nas_encode_ue_security_capability(

View File

@ -65,8 +65,8 @@ status_t mme_ctx_init()
self.srvd_gummei.num_of_mme_code = 1;
self.srvd_gummei.mme_code[0] = 1;
self.selected_enc_algorithm = NAS_SECURITY_ALGORITHMS_EEA0;
self.selected_int_algorithm = NAS_SECURITY_ALGORITHMS_128_EIA1;
self.selected_enc_algorithm = NAS_SECURITY_ALGORITHMS_EIA0;
g_mme_ctx_initialized = 1;

View File

@ -7,6 +7,7 @@
#include "core_sha2.h"
#include "3gpp_message.h"
#include "nas_ies.h"
#include "sm.h"
#ifdef __cplusplus
@ -49,18 +50,18 @@ typedef struct _mme_ctx_t {
c_uint32_t mme_ue_s1ap_id; /** mme_ue_s1ap_id generator */
plmn_id_t plmn_id;
/* defined in 'nas_ies.h'
* #define NAS_SECURITY_ALGORITHMS_EIA0 0
* #define NAS_SECURITY_ALGORITHMS_128_EIA1 1
* #define NAS_SECURITY_ALGORITHMS_128_EIA1 2
* #define NAS_SECURITY_ALGORITHMS_128_EIA3 3 */
c_uint8_t selected_int_algorithm;
/* defined in 'nas_ies.h'
* #define NAS_SECURITY_ALGORITHMS_EIA0 0
* #define NAS_SECURITY_ALGORITHMS_128_EEA1 1
* #define NAS_SECURITY_ALGORITHMS_128_EEA2 2
* #define NAS_SECURITY_ALGORITHMS_128_EEA3 3 */
c_uint8_t selected_enc_algorithm;
/* defined in 'nas_ies.h'
* #define NAS_SECURITY_ALGORITHMS_EIA0 0
* #define NAS_SECURITY_ALGORITHMS_128_EIA1 1
* #define NAS_SECURITY_ALGORITHMS_128_EIA1 2
* #define NAS_SECURITY_ALGORITHMS_128_EIA3 3 */
c_uint8_t selected_int_algorithm;
/* S1SetupRequest */
c_uint16_t tracking_area_code;
@ -96,6 +97,8 @@ typedef struct _ue_ctx_t {
c_uint8_t imsi_len;
/* Security Context */
nas_ue_network_capability_t ue_network_capability;
nas_ms_network_capability_t ms_network_capability;
c_uint8_t xres[MAX_RES_LEN];
c_uint8_t xres_len;
c_uint8_t kasme[SHA256_DIGEST_SIZE];

View File

@ -198,8 +198,6 @@ static void enb_s1ap_handle_s1_setup_request(
d_assert(s1ap_build_setup_rsp(&sendbuf) == CORE_OK,
return, "build error");
d_assert(s1ap_send_to_enb(enb, sendbuf) == CORE_OK, , "send error");
pkbuf_free(sendbuf);
}
static void enb_s1ap_handle_initial_ue_message(

View File

@ -188,9 +188,13 @@ status_t s1ap_send(net_sock_t *s, pkbuf_t *pkbuf)
status_t s1ap_send_to_enb(enb_ctx_t *enb, pkbuf_t *pkbuf)
{
status_t rv;
d_assert(enb, return CORE_ERROR, "Null param");
d_assert(pkbuf, return CORE_ERROR, "Null param");
d_assert(enb->s1ap_sock, return CORE_ERROR, "No S1 path with ENB");
return s1ap_send(enb->s1ap_sock, pkbuf);
rv = s1ap_send(enb->s1ap_sock, pkbuf);
pkbuf_free(pkbuf);
return rv;
}

View File

@ -15,11 +15,12 @@
#include "nas_conv.h"
#include "s6a_sm.h"
static void ue_emm_handle_attach_request(ue_ctx_t *ue, nas_message_t *message);
static void ue_emm_handle_authentication_request(
ue_ctx_t *ue, pkbuf_t *recvbuf);
static void ue_emm_handle_attach_request(
ue_ctx_t *ue, nas_attach_request_t *attach_request);
static void ue_emm_handle_authentication_response(
ue_ctx_t *ue, nas_message_t *message);
ue_ctx_t *ue, nas_authentication_response_t *authentication_response);
static void ue_emm_send_to_ue(ue_ctx_t *ue, pkbuf_t *pkbuf);
void ue_emm_state_initial(ue_emm_sm_t *s, event_t *e)
{
@ -75,17 +76,27 @@ void ue_emm_state_operational(ue_emm_sm_t *s, event_t *e)
{
case NAS_ATTACH_REQUEST:
{
ue_emm_handle_attach_request(ue, &message);
ue_emm_handle_attach_request(
ue, &message.emm.attach_request);
break;
}
case NAS_AUTHENTICATION_REQUEST:
{
ue_emm_handle_authentication_request(ue, recvbuf);
ue_emm_send_to_ue(ue, recvbuf);
d_assert(ue->imsi, return, "no UE-IMSI");
d_info("EMM sends Authentication-Request to UE[%s]",
ue->imsi);
break;
}
case NAS_AUTHENTICATION_RESPONSE:
{
ue_emm_handle_authentication_response(ue, &message);
ue_emm_handle_authentication_response(
ue, &message.emm.authentication_response);
break;
}
case NAS_SECURITY_MODE_COMPLETE:
{
break;
}
default:
@ -132,9 +143,9 @@ void ue_emm_state_exception(ue_emm_sm_t *s, event_t *e)
}
}
static void ue_emm_handle_attach_request(ue_ctx_t *ue, nas_message_t *message)
static void ue_emm_handle_attach_request(
ue_ctx_t *ue, nas_attach_request_t *attach_request)
{
nas_attach_request_t *attach_request = &message->emm.attach_request;
nas_eps_mobile_identity_t *eps_mobile_identity =
&attach_request->eps_mobile_identity;
@ -154,11 +165,17 @@ static void ue_emm_handle_attach_request(ue_ctx_t *ue, nas_message_t *message)
nas_plmn_bcd_to_buffer(
&last_visited_registered_tai->plmn, plmn_id);
}
nas_imsi_bcd_to_buffer(
&eps_mobile_identity->imsi, eps_mobile_identity->length,
ue->imsi, &ue->imsi_len);
memcpy(&ue->ue_network_capability,
&attach_request->ue_network_capability,
sizeof(attach_request->ue_network_capability));
memcpy(&ue->ms_network_capability,
&attach_request->ms_network_capability,
sizeof(attach_request->ms_network_capability));
s6a_send_auth_info_req(ue, plmn_id);
break;
}
@ -167,12 +184,81 @@ static void ue_emm_handle_attach_request(ue_ctx_t *ue, nas_message_t *message)
d_warn("Not implemented(type:%d)",
eps_mobile_identity->imsi.type_of_identity);
break;
return;
}
}
d_assert(ue->imsi, return, "no UE-IMSI");
d_info("UE[%s] sends Attach-Request", ue->imsi);
}
static void ue_emm_handle_authentication_request(ue_ctx_t *ue, pkbuf_t *recvbuf)
static void ue_emm_handle_authentication_response(
ue_ctx_t *ue, nas_authentication_response_t *authentication_response)
{
nas_authentication_response_parameter_t *authentication_response_parameter =
&authentication_response->authentication_response_parameter;
nas_message_t message;
pkbuf_t *sendbuf = NULL;
nas_security_mode_command_t *security_mode_command =
&message.emm.security_mode_command;
nas_security_algorithms_t *selected_nas_security_algorithms =
&security_mode_command->selected_nas_security_algorithms;
nas_key_set_identifier_t *nas_key_set_identifier =
&security_mode_command->nas_key_set_identifier;
nas_ue_security_capability_t *replayed_ue_security_capabilities =
&security_mode_command->replayed_ue_security_capabilities;
d_assert(ue, return, "Null param");
if (authentication_response_parameter->length != ue->xres_len ||
memcmp(authentication_response_parameter->res,
ue->xres, ue->xres_len) != 0)
{
d_error("authentication failed");
return;
}
memset(&message, 0, sizeof(message));
message.h.protocol_discriminator = NAS_PROTOCOL_DISCRIMINATOR_EMM;
message.h.message_type = NAS_SECURITY_MODE_COMMAND;
selected_nas_security_algorithms->type_of_ciphering_algorithm =
mme_self()->selected_enc_algorithm;
selected_nas_security_algorithms->type_of_integrity_protection_algorithm =
mme_self()->selected_int_algorithm;
nas_key_set_identifier->tsc = 0;
nas_key_set_identifier->nas_key_set_identifier = 0;
replayed_ue_security_capabilities->length =
sizeof(replayed_ue_security_capabilities->eea) +
sizeof(replayed_ue_security_capabilities->eia) +
sizeof(replayed_ue_security_capabilities->uea) +
sizeof(replayed_ue_security_capabilities->uia) +
sizeof(replayed_ue_security_capabilities->gea);
replayed_ue_security_capabilities->eea = ue->ue_network_capability.eea;
replayed_ue_security_capabilities->eia = ue->ue_network_capability.eia;
replayed_ue_security_capabilities->uea = ue->ue_network_capability.uea;
replayed_ue_security_capabilities->uia = ue->ue_network_capability.uia;
replayed_ue_security_capabilities->gea =
(ue->ms_network_capability.gea1 << 6) |
ue->ms_network_capability.extended_gea;
mme_kdf_nas(MME_KDF_NAS_INT_ALG, mme_self()->selected_int_algorithm,
ue->kasme, ue->knas_int);
mme_kdf_nas(MME_KDF_NAS_ENC_ALG, mme_self()->selected_enc_algorithm,
ue->kasme, ue->knas_enc);
d_assert(nas_encode_pdu(&sendbuf, &message) == CORE_OK && sendbuf,,);
ue_emm_send_to_ue(ue, sendbuf);
d_assert(ue->imsi, return, "no UE-IMSI");
d_info("EMM sends Security-mode Command to UE[%s]",
ue->imsi);
}
static void ue_emm_send_to_ue(ue_ctx_t *ue, pkbuf_t *pkbuf)
{
int encoded;
s1ap_message_t message;
@ -186,9 +272,9 @@ static void ue_emm_handle_authentication_request(ue_ctx_t *ue, pkbuf_t *recvbuf)
ies->mme_ue_s1ap_id = ue->mme_ue_s1ap_id;
ies->eNB_UE_S1AP_ID = ue->enb_ue_s1ap_id;
nasPdu->size = recvbuf->len;
nasPdu->size = pkbuf->len;
nasPdu->buf = core_calloc(nasPdu->size, sizeof(c_uint8_t));
memcpy(nasPdu->buf, recvbuf->payload, nasPdu->size);
memcpy(nasPdu->buf, pkbuf->payload, nasPdu->size);
message.procedureCode = S1ap_ProcedureCode_id_downlinkNASTransport;
message.direction = S1AP_PDU_PR_initiatingMessage;
@ -198,29 +284,4 @@ static void ue_emm_handle_authentication_request(ue_ctx_t *ue, pkbuf_t *recvbuf)
d_assert(encoded >= 0, , "encode failed");
d_assert(s1ap_send_to_enb(ue->enb, sendbuf) == CORE_OK, , "send error");
pkbuf_free(recvbuf);
}
static void ue_emm_handle_authentication_response(
ue_ctx_t *ue, nas_message_t *message)
{
nas_authentication_response_t *authentication_response =
&message->emm.authentication_response;
nas_authentication_response_parameter_t *authentication_response_parameter =
&authentication_response->authentication_response_parameter;
d_assert(ue, return, "Null param");
if (authentication_response_parameter->length != ue->xres_len ||
memcmp(authentication_response_parameter->res,
ue->xres, ue->xres_len) != 0)
{
d_error("authentication failed");
return;
}
mme_kdf_nas(MME_KDF_NAS_INT_ALG, mme_self()->selected_int_algorithm,
ue->kasme, ue->knas_int);
mme_kdf_nas(MME_KDF_NAS_ENC_ALG, mme_self()->selected_enc_algorithm,
ue->kasme, ue->knas_enc);
}

View File

@ -56,6 +56,19 @@ static void nas_sm_test1(abts_case *tc, void *data)
ABTS_INT_EQUAL(tc, CORE_OK, rv);
pkbuf_free(sendbuf);
/* Receive Security-mode-Command */
recvbuf = pkbuf_alloc(0, MESSAGE_SDU_SIZE);
rc = tests1ap_enb_read(sock, recvbuf);
ABTS_INT_NEQUAL(tc, 0, rc);
pkbuf_free(recvbuf);
/* Send Security-mode-Complete */
rv = tests1ap_build_security_mode_complete(&sendbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
rv = tests1ap_enb_send(sock, sendbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
pkbuf_free(sendbuf);
/* eNB disonncect from MME */
rv = tests1ap_enb_close(sock);
ABTS_INT_EQUAL(tc, CORE_OK, rv);

View File

@ -147,3 +147,20 @@ status_t tests1ap_build_authentication_response(pkbuf_t **pkbuf)
return CORE_OK;
}
status_t tests1ap_build_security_mode_complete(pkbuf_t **pkbuf)
{
char *payload =
"000d403500000500 000005c00100009d"
"000800020001001a 000908476b8f5f64"
"00075e0064400800 00f1101079baf000"
"4340060000f1105b a0";
*pkbuf = pkbuf_alloc(0, MESSAGE_SDU_SIZE);
if (!(*pkbuf)) return CORE_ERROR;
core_ascii_to_hex(payload, strlen(payload), (*pkbuf)->payload);
(*pkbuf)->len = 57;
return CORE_OK;
}

View File

@ -16,6 +16,7 @@ CORE_DECLARE(status_t) tests1ap_build_setup_req(
pkbuf_t **pkbuf, c_uint32_t enb_id);
CORE_DECLARE(status_t) tests1ap_build_initial_ue_msg(pkbuf_t **pkbuf);
CORE_DECLARE(status_t) tests1ap_build_authentication_response(pkbuf_t **pkbuf);
CORE_DECLARE(status_t) tests1ap_build_security_mode_complete(pkbuf_t **pkbuf);
#ifdef __cplusplus
}