From 48bc61d06af64fe0cef874f1b8a35aa4d640291e Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Tue, 7 Mar 2017 14:47:17 +0900 Subject: [PATCH] security-mode complete --- lib/nas/nas_ies.h | 189 ++++++++++++++++++++++++++---------------- src/mme/context.c | 2 +- src/mme/context.h | 15 ++-- src/mme/enb_s1ap_sm.c | 2 - src/mme/s1ap_path.c | 6 +- src/mme/ue_emm_sm.c | 139 ++++++++++++++++++++++--------- test/nas_sm_test.c | 13 +++ test/tests1ap.c | 17 ++++ test/tests1ap.h | 1 + 9 files changed, 263 insertions(+), 121 deletions(-) diff --git a/lib/nas/nas_ies.h b/lib/nas/nas_ies.h index d69d1d8768..ffe8f32101 100644 --- a/lib/nas/nas_ies.h +++ b/lib/nas/nas_ies.h @@ -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( diff --git a/src/mme/context.c b/src/mme/context.c index 2663dbf25c..ad9d1f16fb 100644 --- a/src/mme/context.c +++ b/src/mme/context.c @@ -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; diff --git a/src/mme/context.h b/src/mme/context.h index a89ebd145f..37a2b8c2e3 100644 --- a/src/mme/context.h +++ b/src/mme/context.h @@ -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]; diff --git a/src/mme/enb_s1ap_sm.c b/src/mme/enb_s1ap_sm.c index 7bdd9ea79f..680e074786 100644 --- a/src/mme/enb_s1ap_sm.c +++ b/src/mme/enb_s1ap_sm.c @@ -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( diff --git a/src/mme/s1ap_path.c b/src/mme/s1ap_path.c index 5c1f752fa0..5adbc7822c 100644 --- a/src/mme/s1ap_path.c +++ b/src/mme/s1ap_path.c @@ -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; } diff --git a/src/mme/ue_emm_sm.c b/src/mme/ue_emm_sm.c index c644e28f94..26ad56dc26 100644 --- a/src/mme/ue_emm_sm.c +++ b/src/mme/ue_emm_sm.c @@ -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); } diff --git a/test/nas_sm_test.c b/test/nas_sm_test.c index c9a408a5d3..86f88f9ce3 100644 --- a/test/nas_sm_test.c +++ b/test/nas_sm_test.c @@ -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); diff --git a/test/tests1ap.c b/test/tests1ap.c index 0f63ff885f..e4b4fa48cc 100644 --- a/test/tests1ap.c +++ b/test/tests1ap.c @@ -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; +} diff --git a/test/tests1ap.h b/test/tests1ap.h index 8432f5c75c..4f7d704b8b 100644 --- a/test/tests1ap.h +++ b/test/tests1ap.h @@ -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 }