open5gs/src/mme/emm-build.c

667 lines
26 KiB
C
Raw Normal View History

2019-06-22 03:11:07 +00:00
/*
* Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com>
*
* This file is part of Open5GS.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
2019-06-11 13:10:47 +00:00
#include "nas-security.h"
#include "emm-build.h"
2019-07-06 14:30:05 +00:00
#include "mme-sm.h"
2017-04-12 13:27:32 +00:00
2019-04-27 14:54:30 +00:00
#undef OGS_LOG_DOMAIN
#define OGS_LOG_DOMAIN __emm_log_domain
2019-11-30 07:45:09 +00:00
ogs_pkbuf_t *emm_build_attach_accept(
mme_ue_t *mme_ue, ogs_pkbuf_t *esmbuf)
{
2020-05-23 02:24:48 +00:00
ogs_nas_eps_message_t message;
2019-11-30 07:45:09 +00:00
ogs_pkbuf_t *pkbuf = NULL;
2020-05-23 02:24:48 +00:00
ogs_nas_eps_attach_accept_t *attach_accept = &message.emm.attach_accept;
2019-09-13 12:07:47 +00:00
ogs_nas_eps_attach_result_t *eps_attach_result =
&attach_accept->eps_attach_result;
2019-09-13 12:07:47 +00:00
ogs_nas_gprs_timer_t *t3412_value = &attach_accept->t3412_value;
int served_tai_index = 0;
2019-09-13 12:07:47 +00:00
ogs_nas_eps_mobile_identity_t *nas_guti = &attach_accept->guti;
ogs_nas_eps_network_feature_support_t *eps_network_feature_support =
&attach_accept->eps_network_feature_support;
2019-09-13 12:07:47 +00:00
ogs_nas_location_area_identification_t *lai =
&attach_accept->location_area_identification;
2019-09-13 12:07:47 +00:00
ogs_nas_mobile_identity_t *ms_identity = &attach_accept->ms_identity;
ogs_nas_mobile_identity_tmsi_t *tmsi = &ms_identity->tmsi;;
2019-04-27 14:54:30 +00:00
ogs_assert(mme_ue);
ogs_assert(esmbuf);
memset(&message, 0, sizeof(message));
message.h.security_header_type =
2019-09-13 12:07:47 +00:00
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2019-09-13 12:07:47 +00:00
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2020-05-23 02:24:48 +00:00
message.emm.h.message_type = OGS_NAS_EPS_ATTACH_ACCEPT;
/* Set EPS Attach Accept Type
*
* BEFORE: set attach accept EPS_ATTACH_TYPE from requested EPS_ATTACH_TYPE
* request EPS_ONLY_ATTACH[1] > serve EPS_ONLY_ATTACH[1]
* request COMBINED_EPS_IMSI_ATTACH[2] > serve COMBINED_EPS_IMSI_ATTACH[2]
* request EPS_EMERGENCY_ATTACH[3] > serve EPS_EMERGENCY_ATTACH[3]
*
* ==> eps_attach_result->result = mme_ue->nas_eps.attach.value;
*
* NOW: set attach accept EPS_ATTACH_TYPE from HSS "Network-Access-Mode"
*
* HSS IMSI[x] Network-Access-Mode[2] > serve EPS_ONLY_ATTACH[1]
*
* HSS IMSI[x] Network-Access-Mode[0] && request EPS_ONLY_ATTACH[1]
* > serve EPS_ONLY_ATTACH[1]
*
* HSS IMSI[x] Network-Access-Mode[0] &&
* request COMBINED_EPS_IMSI_ATTACH[2]
* > serve COMBINED_EPS_IMSI_ATTACH[2]
*
* EXCEPTIONS:
* request EPS_EMERGENCY_ATTACH[3] > serve EPS_EMERGENCY_ATTACH[3]
* HSS IMSI[x] Network-Access-Mode[invalid] > serve as requested
*/
if (mme_ue->network_access_mode == OGS_NETWORK_ACCESS_MODE_ONLY_PACKET) {
/* permit only EPS_ATTACH */
eps_attach_result->result = OGS_NAS_ATTACH_TYPE_EPS_ATTACH;
} else {
eps_attach_result->result = mme_ue->nas_eps.attach.value;
}
if (mme_ue->nas_eps.attach.value != eps_attach_result->result) {
/* print warning if difference in requested/served EPS_ATTACH_TYPE */
switch (mme_ue->nas_eps.attach.value){
case OGS_NAS_ATTACH_TYPE_EPS_ATTACH:
ogs_warn(" Requested EPS_ATTACH_TYPE[1, EPS_ATTACH]");
break;
case OGS_NAS_ATTACH_TYPE_COMBINED_EPS_IMSI_ATTACH:
ogs_warn(" Requested EPS_ATTACH_TYPE[2, "
"COMBINED_EPS_IMSI_ATTACH]");
break;
case OGS_NAS_ATTACH_TYPE_EPS_EMERGENCY_ATTACH:
ogs_warn(" Requested EPS_ATTACH_TYPE[3, "
"EPS_EMERGENCY_ATTACH]");
break;
}
switch (eps_attach_result->result) {
case OGS_NAS_ATTACH_TYPE_EPS_ATTACH:
ogs_warn(" Permitted EPS_ATTACH_TYPE[1, EPS_ATTACH]");
break;
case OGS_NAS_ATTACH_TYPE_COMBINED_EPS_IMSI_ATTACH:
ogs_warn(" Permitted EPS_ATTACH_TYPE[2, "
"COMBINED_EPS_IMSI_ATTACH]");
break;
case OGS_NAS_ATTACH_TYPE_EPS_EMERGENCY_ATTACH:
ogs_warn(" Permitted EPS_ATTACH_TYPE[3, "
"EPS_EMERGENCY_ATTACH]");
break;
}
} else {
switch (eps_attach_result->result) {
case OGS_NAS_ATTACH_TYPE_EPS_ATTACH:
ogs_debug(" EPS_ATTACH_TYPE[1, EPS_ATTACH]");
break;
case OGS_NAS_ATTACH_TYPE_COMBINED_EPS_IMSI_ATTACH:
ogs_debug(" EPS_ATTACH_TYPE[2, COMBINED_EPS_IMSI_ATTACH]");
break;
case OGS_NAS_ATTACH_TYPE_EPS_EMERGENCY_ATTACH:
ogs_debug(" EPS_ATTACH_TYPE[3, EPS_EMERGENCY_ATTACH]");
break;
}
}
/* Set T3412 */
2019-09-13 12:07:47 +00:00
t3412_value->unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH;
t3412_value->value = 9;
2019-04-27 14:54:30 +00:00
ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]",
2019-09-13 12:07:47 +00:00
ogs_plmn_id_hexdump(&mme_ue->tai.plmn_id),
2019-04-27 14:54:30 +00:00
mme_ue->tai.tac);
ogs_debug(" E_CGI[PLMN_ID:%06x,CELL_ID:0x%x]",
2019-09-13 12:07:47 +00:00
ogs_plmn_id_hexdump(&mme_ue->e_cgi.plmn_id),
2019-04-27 14:54:30 +00:00
mme_ue->e_cgi.cell_id);
served_tai_index = mme_find_served_tai(&mme_ue->tai);
2019-04-27 14:54:30 +00:00
ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index);
ogs_assert(served_tai_index >= 0 &&
2020-05-25 16:15:22 +00:00
served_tai_index < OGS_MAX_NUM_OF_SERVED_TAI);
2021-06-06 13:35:46 +00:00
ogs_assert(OGS_OK ==
ogs_nas_tai_list_build(&attach_accept->tai_list,
2017-12-11 07:55:11 +00:00
&mme_self()->served_tai[served_tai_index].list0,
2021-06-06 13:35:46 +00:00
&mme_self()->served_tai[served_tai_index].list2));
2019-04-27 14:54:30 +00:00
attach_accept->esm_message_container.buffer = esmbuf->data;
attach_accept->esm_message_container.length = esmbuf->len;
if (mme_ue->next.m_tmsi) {
2020-05-23 02:24:48 +00:00
attach_accept->presencemask |= OGS_NAS_EPS_ATTACH_ACCEPT_GUTI_PRESENT;
ogs_debug(" [%s] GUTI[G:%d,C:%d,M_TMSI:0x%x]",
mme_ue->imsi_bcd,
mme_ue->next.guti.mme_gid, mme_ue->next.guti.mme_code,
mme_ue->next.guti.m_tmsi);
2019-09-13 12:07:47 +00:00
nas_guti->length = sizeof(ogs_nas_eps_mobile_identity_guti_t);
2020-05-22 01:24:21 +00:00
nas_guti->guti.odd_even = OGS_NAS_MOBILE_IDENTITY_EVEN;
2019-09-13 12:07:47 +00:00
nas_guti->guti.type = OGS_NAS_EPS_MOBILE_IDENTITY_GUTI;
nas_guti->guti.nas_plmn_id = mme_ue->next.guti.nas_plmn_id;
nas_guti->guti.mme_gid = mme_ue->next.guti.mme_gid;
nas_guti->guti.mme_code = mme_ue->next.guti.mme_code;
nas_guti->guti.m_tmsi = mme_ue->next.guti.m_tmsi;
}
#if 0 /* Need not to include T3402 */
/* Set T3402 */
2020-05-23 02:24:48 +00:00
attach_accept->presencemask |= OGS_NAS_EPS_ATTACH_ACCEPT_T3402_VALUE_PRESENT;
2019-09-13 12:07:47 +00:00
attach_accept->t3402_value.unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_1_MM;
attach_accept->t3402_value.value = 12;
#endif
/* Set T3423 */
attach_accept->presencemask |=
OGS_NAS_EPS_ATTACH_ACCEPT_T3423_VALUE_PRESENT;
attach_accept->t3423_value.unit =
OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH;
attach_accept->t3423_value.value = 9;
2020-06-23 04:35:41 +00:00
attach_accept->presencemask |=
2020-05-23 02:24:48 +00:00
OGS_NAS_EPS_ATTACH_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT;
if (ogs_app()->parameter.use_openair == false) {
eps_network_feature_support->length = 2;
} else {
eps_network_feature_support->length = 1;
}
2020-07-03 05:03:13 +00:00
eps_network_feature_support->ims_voice_over_ps_session_in_s1_mode = 1;
eps_network_feature_support->extended_protocol_configuration_options = 1;
2019-07-06 14:30:05 +00:00
if (MME_P_TMSI_IS_AVAILABLE(mme_ue)) {
2019-07-21 11:25:29 +00:00
ogs_assert(mme_ue->csmap);
2019-07-06 14:30:05 +00:00
ogs_assert(mme_ue->p_tmsi);
attach_accept->presencemask |=
2020-05-23 02:24:48 +00:00
OGS_NAS_EPS_ATTACH_ACCEPT_LOCATION_AREA_IDENTIFICATION_PRESENT;
2019-07-21 11:25:29 +00:00
lai->nas_plmn_id = mme_ue->csmap->lai.nas_plmn_id;
lai->lac = mme_ue->csmap->lai.lac;
2019-06-22 03:11:07 +00:00
ogs_debug(" LAI[PLMN_ID:%06x,LAC:%d]",
2019-09-13 12:07:47 +00:00
ogs_plmn_id_hexdump(&lai->nas_plmn_id), lai->lac);
attach_accept->presencemask |=
OGS_NAS_EPS_ATTACH_ACCEPT_MS_IDENTITY_PRESENT;
ms_identity->length = 5;
tmsi->spare = 0xf;
tmsi->odd_even = 0;
2019-09-13 12:07:47 +00:00
tmsi->type = OGS_NAS_MOBILE_IDENTITY_TMSI;
tmsi->tmsi = mme_ue->p_tmsi;
ogs_debug(" P-TMSI: 0x%08x", tmsi->tmsi);
}
2020-05-23 02:24:48 +00:00
pkbuf = nas_eps_security_encode(mme_ue, &message);
2019-04-27 14:54:30 +00:00
ogs_pkbuf_free(esmbuf);
2019-11-30 07:45:09 +00:00
return pkbuf;
}
2019-11-30 07:45:09 +00:00
ogs_pkbuf_t *emm_build_attach_reject(
ogs_nas_emm_cause_t emm_cause, ogs_pkbuf_t *esmbuf)
{
2020-05-23 02:24:48 +00:00
ogs_nas_eps_message_t message;
2019-11-30 07:45:09 +00:00
ogs_pkbuf_t *pkbuf = NULL;
2020-05-23 02:24:48 +00:00
ogs_nas_eps_attach_reject_t *attach_reject = &message.emm.attach_reject;
memset(&message, 0, sizeof(message));
2019-09-13 12:07:47 +00:00
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2020-05-23 02:24:48 +00:00
message.emm.h.message_type = OGS_NAS_EPS_ATTACH_REJECT;
attach_reject->emm_cause = emm_cause;
2019-06-22 03:11:07 +00:00
if (esmbuf) {
2019-11-18 10:34:28 +00:00
attach_reject->presencemask |=
2020-05-23 02:24:48 +00:00
OGS_NAS_EPS_ATTACH_REJECT_ESM_MESSAGE_CONTAINER_PRESENT;
2019-04-27 14:54:30 +00:00
attach_reject->esm_message_container.buffer = esmbuf->data;
attach_reject->esm_message_container.length = esmbuf->len;
}
2020-05-23 02:24:48 +00:00
pkbuf = ogs_nas_eps_plain_encode(&message);
2019-11-30 07:45:09 +00:00
if (esmbuf)
2019-04-27 14:54:30 +00:00
ogs_pkbuf_free(esmbuf);
2019-11-30 07:45:09 +00:00
return pkbuf;
}
2019-11-30 07:45:09 +00:00
ogs_pkbuf_t *emm_build_identity_request(mme_ue_t *mme_ue)
2017-09-04 04:04:35 +00:00
{
2020-05-23 02:24:48 +00:00
ogs_nas_eps_message_t message;
ogs_nas_eps_identity_request_t *identity_request =
2017-09-04 04:04:35 +00:00
&message.emm.identity_request;
2019-04-27 14:54:30 +00:00
ogs_assert(mme_ue);
2017-09-04 04:04:35 +00:00
memset(&message, 0, sizeof(message));
2019-09-13 12:07:47 +00:00
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2020-05-23 02:24:48 +00:00
message.emm.h.message_type = OGS_NAS_EPS_IDENTITY_REQUEST;
2017-09-04 04:04:35 +00:00
/* Request IMSI */
2019-04-27 14:54:30 +00:00
ogs_debug(" Identity Type 2 : IMSI");
2019-09-13 12:07:47 +00:00
identity_request->identity_type.type = OGS_NAS_IDENTITY_TYPE_2_IMSI;
2017-09-04 04:04:35 +00:00
2020-05-23 02:24:48 +00:00
return ogs_nas_eps_plain_encode(&message);
2017-09-11 09:41:14 +00:00
}
ogs_pkbuf_t *emm_build_authentication_request(mme_ue_t *mme_ue)
2017-09-11 09:41:14 +00:00
{
2020-05-23 02:24:48 +00:00
ogs_nas_eps_message_t message;
ogs_nas_eps_authentication_request_t *authentication_request =
2017-09-11 09:41:14 +00:00
&message.emm.authentication_request;
2020-06-23 04:35:41 +00:00
ogs_assert(mme_ue);
2017-09-11 09:41:14 +00:00
memset(&message, 0, sizeof(message));
2019-09-13 12:07:47 +00:00
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2020-05-23 02:24:48 +00:00
message.emm.h.message_type = OGS_NAS_EPS_AUTHENTICATION_REQUEST;
2017-09-11 09:41:14 +00:00
2020-06-23 04:35:41 +00:00
authentication_request->nas_key_set_identifierasme.tsc = 0;
authentication_request->nas_key_set_identifierasme.value =
mme_ue->nas_eps.ksi;
2017-09-11 09:41:14 +00:00
memcpy(authentication_request->authentication_parameter_rand.rand,
mme_ue->rand, OGS_RAND_LEN);
2017-09-11 09:41:14 +00:00
memcpy(authentication_request->authentication_parameter_autn.autn,
mme_ue->autn, OGS_AUTN_LEN);
2017-09-11 09:41:14 +00:00
authentication_request->authentication_parameter_autn.length =
2019-09-13 12:07:47 +00:00
OGS_AUTN_LEN;
2017-09-11 09:41:14 +00:00
2020-05-23 02:24:48 +00:00
return ogs_nas_eps_plain_encode(&message);
2017-09-11 09:41:14 +00:00
}
2019-11-30 07:45:09 +00:00
ogs_pkbuf_t *emm_build_authentication_reject(void)
2017-09-11 09:41:14 +00:00
{
2020-05-23 02:24:48 +00:00
ogs_nas_eps_message_t message;
2017-09-11 09:41:14 +00:00
memset(&message, 0, sizeof(message));
2019-09-13 12:07:47 +00:00
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2020-05-23 02:24:48 +00:00
message.emm.h.message_type = OGS_NAS_EPS_AUTHENTICATION_REJECT;
2017-09-11 09:41:14 +00:00
2020-05-23 02:24:48 +00:00
return ogs_nas_eps_plain_encode(&message);
2017-09-04 04:04:35 +00:00
}
2019-11-30 07:45:09 +00:00
ogs_pkbuf_t *emm_build_security_mode_command(mme_ue_t *mme_ue)
2017-09-04 04:04:35 +00:00
{
2020-05-23 02:24:48 +00:00
ogs_nas_eps_message_t message;
ogs_nas_eps_security_mode_command_t *security_mode_command =
2017-09-04 04:04:35 +00:00
&message.emm.security_mode_command;
2019-09-13 12:07:47 +00:00
ogs_nas_security_algorithms_t *selected_nas_security_algorithms =
2017-09-04 04:04:35 +00:00
&security_mode_command->selected_nas_security_algorithms;
2019-09-13 12:07:47 +00:00
ogs_nas_key_set_identifier_t *nas_key_set_identifier =
2017-09-04 04:04:35 +00:00
&security_mode_command->nas_key_set_identifier;
2019-09-13 12:07:47 +00:00
ogs_nas_ue_security_capability_t *replayed_ue_security_capabilities =
2017-09-04 04:04:35 +00:00
&security_mode_command->replayed_ue_security_capabilities;
2019-11-18 10:34:28 +00:00
ogs_nas_imeisv_request_t *imeisv_request =
&security_mode_command->imeisv_request;
2020-07-03 05:03:13 +00:00
ogs_nas_hashmme_t *hashmme = &security_mode_command->hashmme;
ogs_nas_ue_additional_security_capability_t
*replayed_ue_additional_security_capability =
&security_mode_command->replayed_ue_additional_security_capability;
2017-09-04 04:04:35 +00:00
2019-04-27 14:54:30 +00:00
ogs_assert(mme_ue);
2017-09-04 04:04:35 +00:00
memset(&message, 0, sizeof(message));
message.h.security_header_type =
2019-09-13 12:07:47 +00:00
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_NEW_SECURITY_CONTEXT;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2017-09-04 04:04:35 +00:00
2019-09-13 12:07:47 +00:00
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2020-05-23 02:24:48 +00:00
message.emm.h.message_type = OGS_NAS_EPS_SECURITY_MODE_COMMAND;
2017-09-04 04:04:35 +00:00
mme_ue->selected_int_algorithm = mme_selected_int_algorithm(mme_ue);
mme_ue->selected_enc_algorithm = mme_selected_enc_algorithm(mme_ue);
2017-09-04 04:04:35 +00:00
selected_nas_security_algorithms->type_of_integrity_protection_algorithm =
mme_ue->selected_int_algorithm;
selected_nas_security_algorithms->type_of_ciphering_algorithm =
mme_ue->selected_enc_algorithm;
nas_key_set_identifier->tsc = 0;
2020-05-22 01:24:21 +00:00
nas_key_set_identifier->value = 0;
2017-09-04 04:04:35 +00:00
replayed_ue_security_capabilities->eea = mme_ue->ue_network_capability.eea;
replayed_ue_security_capabilities->eia = mme_ue->ue_network_capability.eia;
replayed_ue_security_capabilities->uea = mme_ue->ue_network_capability.uea;
2018-03-05 19:02:36 +00:00
replayed_ue_security_capabilities->uia =
mme_ue->ue_network_capability.uia & 0x7f;
2017-09-04 04:04:35 +00:00
replayed_ue_security_capabilities->gea =
(mme_ue->ms_network_capability.gea1 << 6) |
mme_ue->ms_network_capability.extended_gea;
replayed_ue_security_capabilities->length =
sizeof(replayed_ue_security_capabilities->eea) +
sizeof(replayed_ue_security_capabilities->eia);
if (replayed_ue_security_capabilities->uea ||
replayed_ue_security_capabilities->uia)
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);
if (replayed_ue_security_capabilities->gea)
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);
2020-06-23 04:35:41 +00:00
ogs_debug(" Replayed UE SEC[LEN:%d EEA:0x%x EIA:0x%x UEA:0x%x "
"UIA:0x%x GEA:0x%x]",
replayed_ue_security_capabilities->length,
replayed_ue_security_capabilities->eea,
replayed_ue_security_capabilities->eia,
replayed_ue_security_capabilities->uea,
replayed_ue_security_capabilities->uia,
replayed_ue_security_capabilities->gea);
2019-04-27 14:54:30 +00:00
ogs_debug(" Selected[Integrity:0x%x Encrypt:0x%x]",
2019-04-02 02:11:24 +00:00
mme_ue->selected_int_algorithm, mme_ue->selected_enc_algorithm);
2019-11-18 10:34:28 +00:00
security_mode_command->presencemask |=
2020-05-23 02:24:48 +00:00
OGS_NAS_EPS_SECURITY_MODE_COMMAND_IMEISV_REQUEST_PRESENT;
2019-11-18 10:34:28 +00:00
imeisv_request->type = OGS_NAS_IMEISV_TYPE;
2020-06-17 05:22:28 +00:00
imeisv_request->value = OGS_NAS_IMEISV_REQUESTED;
2019-11-18 10:34:28 +00:00
/*
* TS24.301
* 5.4.3.2 NAS security mode control initiation by the network
*
* If, during an ongoing attach or tracking area updating procedure,
* the MME is initiating a SECURITY MODE COMMAND (i.e. after receiving
* the ATTACH REQUEST or TRACKING AREA UPDATE REQUEST message,
* but before sending a response to that message) and the ATTACH REQUEST
* or TRACKING AREA UPDATE REQUEST message is received without integrity
* protection or does not successfully pass the integrity check at the MME,
* the MME shall calculate the HASH MME of the entire plain ATTACH REQUEST
* or TRACKING AREA UPDATE REQUEST message as described
* in 3GPP TS 33.401 [19] and shall include the HASH MME
* in the SECURITY MODE COMMAND message
*
* However, Openair UE does not support HashMME. For user convenience,
* we added a way not to include HashMME through the configuration file.
*/
if (ogs_app()->parameter.use_openair == false) {
security_mode_command->presencemask |=
OGS_NAS_EPS_SECURITY_MODE_COMMAND_HASHMME_PRESENT;
hashmme->length = OGS_HASH_MME_LEN;
memcpy(hashmme->value, mme_ue->hash_mme, hashmme->length);
}
2020-07-03 05:03:13 +00:00
if (mme_ue->ue_additional_security_capability.length) {
security_mode_command->presencemask |=
OGS_NAS_EPS_SECURITY_MODE_COMMAND_REPLAYED_UE_ADDITIONAL_SECURITY_CAPABILITY_PRESENT;
memcpy(replayed_ue_additional_security_capability,
&mme_ue->ue_additional_security_capability,
sizeof(mme_ue->ue_additional_security_capability));
}
2019-09-13 12:07:47 +00:00
if (mme_ue->selected_int_algorithm == OGS_NAS_SECURITY_ALGORITHMS_EIA0) {
2019-11-30 07:45:09 +00:00
ogs_error("Encrypt[0x%x] can be skipped with EEA0, "
2019-04-27 14:54:30 +00:00
"but Integrity[0x%x] cannot be bypassed with EIA0",
2019-04-02 02:11:24 +00:00
mme_ue->selected_enc_algorithm, mme_ue->selected_int_algorithm);
2019-11-30 07:45:09 +00:00
return NULL;
2019-04-02 02:11:24 +00:00
}
2020-06-04 18:12:05 +00:00
ogs_kdf_nas_eps(OGS_KDF_NAS_INT_ALG, mme_ue->selected_int_algorithm,
2017-09-04 04:04:35 +00:00
mme_ue->kasme, mme_ue->knas_int);
2020-06-04 18:12:05 +00:00
ogs_kdf_nas_eps(OGS_KDF_NAS_ENC_ALG, mme_ue->selected_enc_algorithm,
2017-09-04 04:04:35 +00:00
mme_ue->kasme, mme_ue->knas_enc);
2020-05-23 02:24:48 +00:00
return nas_eps_security_encode(mme_ue, &message);
2017-09-04 04:04:35 +00:00
}
2019-11-30 07:45:09 +00:00
ogs_pkbuf_t *emm_build_detach_accept(mme_ue_t *mme_ue)
2017-04-12 13:27:32 +00:00
{
2020-05-23 02:24:48 +00:00
ogs_nas_eps_message_t message;
2017-04-12 13:27:32 +00:00
2019-04-27 14:54:30 +00:00
ogs_assert(mme_ue);
2017-04-12 13:27:32 +00:00
memset(&message, 0, sizeof(message));
message.h.security_header_type =
2019-09-13 12:07:47 +00:00
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2017-04-12 13:27:32 +00:00
2019-09-13 12:07:47 +00:00
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2020-05-23 02:24:48 +00:00
message.emm.h.message_type = OGS_NAS_EPS_DETACH_ACCEPT;
2017-08-11 03:05:01 +00:00
2020-05-23 02:24:48 +00:00
return nas_eps_security_encode(mme_ue, &message);
2017-08-11 03:05:01 +00:00
}
2019-11-30 07:45:09 +00:00
ogs_pkbuf_t *emm_build_tau_accept(mme_ue_t *mme_ue)
2017-08-23 23:53:44 +00:00
{
2020-05-23 02:24:48 +00:00
ogs_nas_eps_message_t message;
ogs_nas_eps_tracking_area_update_accept_t *tau_accept =
2017-08-23 23:53:44 +00:00
&message.emm.tracking_area_update_accept;
ogs_nas_eps_mobile_identity_t *nas_guti = &tau_accept->guti;
2017-12-11 07:55:11 +00:00
int served_tai_index = 0;
2017-08-23 23:53:44 +00:00
mme_sess_t *sess = NULL;
2019-04-27 14:54:30 +00:00
ogs_assert(mme_ue);
2018-01-22 14:14:20 +00:00
2017-08-23 23:53:44 +00:00
memset(&message, 0, sizeof(message));
message.h.security_header_type =
2019-09-13 12:07:47 +00:00
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2019-09-13 12:07:47 +00:00
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2020-05-23 02:24:48 +00:00
message.emm.h.message_type = OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT;
2017-08-23 23:53:44 +00:00
if (mme_ue->nas_eps.update.value ==
OGS_NAS_EPS_UPDATE_TYPE_COMBINED_TA_LA_UPDATING ||
mme_ue->nas_eps.update.value ==
OGS_NAS_EPS_UPDATE_TYPE_COMBINED_TA_LA_UPDATING_WITH_IMSI_ATTACH) {
tau_accept->eps_update_result.result =
OGS_NAS_EPS_UPDATE_RESULT_COMBINED_TA_LA_UPDATED;
} else {
tau_accept->eps_update_result.result =
OGS_NAS_EPS_UPDATE_RESULT_TA_UPDATED;
}
2017-08-23 23:53:44 +00:00
/* Set T3412 */
2019-11-18 10:34:28 +00:00
tau_accept->presencemask |=
2020-05-23 02:24:48 +00:00
OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_T3412_VALUE_PRESENT ;
2019-09-13 12:07:47 +00:00
tau_accept->t3412_value.unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH;
2017-08-23 23:53:44 +00:00
tau_accept->t3412_value.value = 9;
if (mme_ue->next.m_tmsi) {
tau_accept->presencemask |=
OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_GUTI_PRESENT;
ogs_debug("[%s] GUTI[G:%d,C:%d,M_TMSI:0x%x]",
mme_ue->imsi_bcd,
mme_ue->next.guti.mme_gid, mme_ue->next.guti.mme_code,
mme_ue->next.guti.m_tmsi);
nas_guti->length = sizeof(ogs_nas_eps_mobile_identity_guti_t);
nas_guti->guti.odd_even = OGS_NAS_MOBILE_IDENTITY_EVEN;
nas_guti->guti.type = OGS_NAS_EPS_MOBILE_IDENTITY_GUTI;
nas_guti->guti.nas_plmn_id = mme_ue->next.guti.nas_plmn_id;
nas_guti->guti.mme_gid = mme_ue->next.guti.mme_gid;
nas_guti->guti.mme_code = mme_ue->next.guti.mme_code;
nas_guti->guti.m_tmsi = mme_ue->next.guti.m_tmsi;
}
2017-08-23 23:53:44 +00:00
/* Set TAI */
2019-11-18 10:34:28 +00:00
tau_accept->presencemask |=
2020-05-23 02:24:48 +00:00
OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_TAI_LIST_PRESENT;
2017-08-23 23:53:44 +00:00
2019-04-27 14:54:30 +00:00
ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]",
2019-09-13 12:07:47 +00:00
ogs_plmn_id_hexdump(&mme_ue->tai.plmn_id),
2019-04-27 14:54:30 +00:00
mme_ue->tai.tac);
ogs_debug(" E_CGI[PLMN_ID:%06x,CELL_ID:0x%x]",
2019-09-13 12:07:47 +00:00
ogs_plmn_id_hexdump(&mme_ue->e_cgi.plmn_id),
2019-04-27 14:54:30 +00:00
mme_ue->e_cgi.cell_id);
2017-12-11 07:55:11 +00:00
served_tai_index = mme_find_served_tai(&mme_ue->tai);
2019-04-27 14:54:30 +00:00
ogs_debug(" SERVED_TAI_INDEX[%d]", served_tai_index);
ogs_assert(served_tai_index >= 0 &&
2020-05-25 16:15:22 +00:00
served_tai_index < OGS_MAX_NUM_OF_SERVED_TAI);
2021-06-06 13:35:46 +00:00
ogs_assert(OGS_OK ==
ogs_nas_tai_list_build(&tau_accept->tai_list,
2017-12-11 07:55:11 +00:00
&mme_self()->served_tai[served_tai_index].list0,
2021-06-06 13:35:46 +00:00
&mme_self()->served_tai[served_tai_index].list2));
2017-08-23 23:53:44 +00:00
/* Set EPS bearer context status */
2019-11-18 10:34:28 +00:00
tau_accept->presencemask |=
2020-05-23 02:24:48 +00:00
OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_EPS_BEARER_CONTEXT_STATUS_PRESENT;
2017-08-23 23:53:44 +00:00
tau_accept->eps_bearer_context_status.length = 2;
sess = mme_sess_first(mme_ue);
2019-06-22 03:11:07 +00:00
while (sess) {
mme_bearer_t *bearer = mme_bearer_first(sess);
2019-06-22 03:11:07 +00:00
while (bearer) {
2020-09-02 03:04:35 +00:00
switch (bearer->ebi) {
2019-06-22 03:11:07 +00:00
case 5: tau_accept->eps_bearer_context_status.ebi5 = 1; break;
case 6: tau_accept->eps_bearer_context_status.ebi6 = 1; break;
case 7: tau_accept->eps_bearer_context_status.ebi7 = 1; break;
case 8: tau_accept->eps_bearer_context_status.ebi8 = 1; break;
case 9: tau_accept->eps_bearer_context_status.ebi9 = 1; break;
case 10: tau_accept->eps_bearer_context_status.ebi10 = 1; break;
case 11: tau_accept->eps_bearer_context_status.ebi11 = 1; break;
case 12: tau_accept->eps_bearer_context_status.ebi12 = 1; break;
case 13: tau_accept->eps_bearer_context_status.ebi13 = 1; break;
case 14: tau_accept->eps_bearer_context_status.ebi14 = 1; break;
case 15: tau_accept->eps_bearer_context_status.ebi15 = 1; break;
default: break;
}
bearer = mme_bearer_next(bearer);
}
sess = mme_sess_next(sess);
}
2017-08-23 23:53:44 +00:00
#if 0 /* Need not to include T3402 */
2017-08-23 23:53:44 +00:00
/* Set T3402 */
2019-11-18 10:34:28 +00:00
tau_accept->presencemask |=
2020-05-23 02:24:48 +00:00
OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_T3402_VALUE_PRESENT;
2019-09-13 12:07:47 +00:00
tau_accept->t3402_value.unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_1_MM;
2017-08-23 23:53:44 +00:00
tau_accept->t3402_value.value = 12;
#endif
2017-08-23 23:53:44 +00:00
/* Set T3423 */
2019-11-18 10:34:28 +00:00
tau_accept->presencemask |=
2020-05-23 02:24:48 +00:00
OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_T3423_VALUE_PRESENT;
2019-09-13 12:07:47 +00:00
tau_accept->t3423_value.unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH;
2017-08-23 23:53:44 +00:00
tau_accept->t3423_value.value = 9;
/* Set EPS network feature support */
2019-11-18 10:34:28 +00:00
tau_accept->presencemask |=
2020-05-23 02:24:48 +00:00
OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT;
if (ogs_app()->parameter.use_openair == false) {
tau_accept->eps_network_feature_support.length = 2;
} else {
tau_accept->eps_network_feature_support.length = 1;
}
2020-07-03 05:03:13 +00:00
tau_accept->eps_network_feature_support.
ims_voice_over_ps_session_in_s1_mode = 1;
tau_accept->eps_network_feature_support.
extended_protocol_configuration_options = 1;
2017-08-23 23:53:44 +00:00
2020-05-23 02:24:48 +00:00
return nas_eps_security_encode(mme_ue, &message);
2017-08-23 23:53:44 +00:00
}
2019-11-30 07:45:09 +00:00
ogs_pkbuf_t *emm_build_tau_reject(
ogs_nas_emm_cause_t emm_cause, mme_ue_t *mme_ue)
2017-08-23 23:53:44 +00:00
{
2020-05-23 02:24:48 +00:00
ogs_nas_eps_message_t message;
ogs_nas_eps_tracking_area_update_reject_t *tau_reject =
2017-08-23 23:53:44 +00:00
&message.emm.tracking_area_update_reject;
2019-04-27 14:54:30 +00:00
ogs_assert(mme_ue);
2018-01-22 14:14:20 +00:00
ogs_debug(" Cause[%d]", emm_cause);
2018-01-22 14:14:20 +00:00
2017-08-23 23:53:44 +00:00
memset(&message, 0, sizeof(message));
2019-09-13 12:07:47 +00:00
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2020-05-23 02:24:48 +00:00
message.emm.h.message_type = OGS_NAS_EPS_TRACKING_AREA_UPDATE_REJECT;
2017-08-23 23:53:44 +00:00
tau_reject->emm_cause = emm_cause;
2020-05-23 02:24:48 +00:00
return ogs_nas_eps_plain_encode(&message);
2017-08-23 23:53:44 +00:00
}
2017-09-08 22:56:42 +00:00
2019-11-30 07:45:09 +00:00
ogs_pkbuf_t *emm_build_service_reject(
ogs_nas_emm_cause_t emm_cause, mme_ue_t *mme_ue)
2017-09-08 22:56:42 +00:00
{
2020-05-23 02:24:48 +00:00
ogs_nas_eps_message_t message;
ogs_nas_eps_service_reject_t *service_reject = &message.emm.service_reject;
2017-09-08 22:56:42 +00:00
2019-04-27 14:54:30 +00:00
ogs_assert(mme_ue);
2017-09-08 22:56:42 +00:00
memset(&message, 0, sizeof(message));
2019-09-13 12:07:47 +00:00
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2020-05-23 02:24:48 +00:00
message.emm.h.message_type = OGS_NAS_EPS_SERVICE_REJECT;
2017-09-08 22:56:42 +00:00
service_reject->emm_cause = emm_cause;
2020-05-23 02:24:48 +00:00
return ogs_nas_eps_plain_encode(&message);
2017-09-08 22:56:42 +00:00
}
2019-07-11 09:14:32 +00:00
2019-11-30 07:45:09 +00:00
ogs_pkbuf_t *emm_build_cs_service_notification(mme_ue_t *mme_ue)
2019-07-11 09:14:32 +00:00
{
2020-05-23 02:24:48 +00:00
ogs_nas_eps_message_t message;
ogs_nas_eps_cs_service_notification_t *cs_service_notification =
2019-07-11 09:14:32 +00:00
&message.emm.cs_service_notification;
2019-09-13 12:07:47 +00:00
ogs_nas_paging_identity_t *paging_identity =
2019-07-11 09:14:32 +00:00
&cs_service_notification->paging_identity;
ogs_assert(mme_ue);
memset(&message, 0, sizeof(message));
message.h.security_header_type =
2019-09-13 12:07:47 +00:00
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2019-07-11 09:14:32 +00:00
2019-09-13 12:07:47 +00:00
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2020-05-23 02:24:48 +00:00
message.emm.h.message_type = OGS_NAS_EPS_CS_SERVICE_NOTIFICATION;
2019-07-11 09:14:32 +00:00
/* FIXME : Does it right to use TMSI */
2019-09-13 12:07:47 +00:00
paging_identity->identity = OGS_NAS_PAGING_IDENTITY_TMSI;
2019-07-11 09:14:32 +00:00
ogs_debug(" Paging Identity[%d]", paging_identity->identity);
/* FIXME : What optional filed should be included in this message? */
2020-05-23 02:24:48 +00:00
return nas_eps_security_encode(mme_ue, &message);
2019-07-11 09:14:32 +00:00
}
2019-11-30 07:45:09 +00:00
ogs_pkbuf_t *emm_build_downlink_nas_transport(
mme_ue_t *mme_ue, uint8_t *buffer, uint8_t length)
2019-07-13 13:52:50 +00:00
{
2020-05-23 02:24:48 +00:00
ogs_nas_eps_message_t message;
ogs_nas_eps_downlink_nas_transport_t *downlink_nas_transport =
2019-07-13 13:52:50 +00:00
&message.emm.downlink_nas_transport;
2020-05-23 02:24:48 +00:00
ogs_nas_eps_message_container_t *nas_message_container =
2019-07-13 13:52:50 +00:00
&downlink_nas_transport->nas_message_container;
ogs_assert(mme_ue);
memset(&message, 0, sizeof(message));
message.h.security_header_type =
2019-09-13 12:07:47 +00:00
OGS_NAS_SECURITY_HEADER_INTEGRITY_PROTECTED_AND_CIPHERED;
message.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2019-07-13 13:52:50 +00:00
2019-09-13 12:07:47 +00:00
message.emm.h.protocol_discriminator = OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM;
2020-05-23 02:24:48 +00:00
message.emm.h.message_type = OGS_NAS_EPS_DOWNLINK_NAS_TRANSPORT;
2019-07-13 13:52:50 +00:00
nas_message_container->length = length;
memcpy(nas_message_container->buffer, buffer, length);
2020-05-23 02:24:48 +00:00
return nas_eps_security_encode(mme_ue, &message);
2019-07-13 13:52:50 +00:00
}