Support SMF Security Indication IE (#1851)

This commit is contained in:
Sukchan Lee 2022-10-29 12:26:09 +09:00
parent f1c0b6d239
commit 0df2cba257
4 changed files with 262 additions and 1 deletions

View File

@ -440,7 +440,20 @@ logger:
# mnc: 70
# tac: 99
#
# <Security Indication - 5G Core only>
#
# According to 3GPP TS38.413 Section 9.3.1.27,
# Security Indication IE may be instructed to 5G gNB.
#
# If you set the security_indication in smf.yaml,
# this information is delivered using PDU Session Resource Request Transfer IE
#
# security_indication:
# integrity_protection_indication: required|preferred|not-needed
# confidentiality_protection_indication: required|preferred|not-needed
# maximum_integrity_protected_data_rate_uplink: bitrate64kbs|maximum-UE-rate
# maximum_integrity_protected_data_rate_downlink: bitrate64kbs|maximum-UE-rate
#
smf:
sbi:
- addr: 127.0.0.4

View File

@ -202,6 +202,83 @@ static int smf_context_validation(void)
}
}
if (self.security_indication.integrity_protection_indication ||
self.security_indication.confidentiality_protection_indication) {
if (!self.security_indication.integrity_protection_indication ||
!self.security_indication.confidentiality_protection_indication) {
ogs_error("Invalid security_indication [%s,%s]",
self.security_indication.integrity_protection_indication ?
self.security_indication.integrity_protection_indication :
"No integrity_protection_indication",
self.security_indication.confidentiality_protection_indication ?
self.security_indication.confidentiality_protection_indication :
"No confidentiality_protection_indication");
return OGS_ERROR;
}
if (smf_integrity_protection_indication_value2enum(
self.security_indication.integrity_protection_indication) < 0) {
ogs_error("Invalid integrity_protection_indication [%s]",
self.security_indication.integrity_protection_indication);
return OGS_ERROR;
}
if (smf_confidentiality_protection_indication_value2enum(
self.security_indication.
confidentiality_protection_indication) < 0) {
ogs_error("Invalid confidentiality_protection_indication [%s]",
self.security_indication.confidentiality_protection_indication);
return OGS_ERROR;
}
}
if (self.security_indication.maximum_integrity_protected_data_rate_uplink) {
NGAP_IntegrityProtectionIndication_t integrityProtectionIndication;
if (smf_maximum_integrity_protected_data_rate_uplink_value2enum(
self.security_indication.
maximum_integrity_protected_data_rate_uplink) < 0) {
ogs_error("Invalid "
"maximum_integrity_protected_data_rate_uplink [%s]",
self.security_indication.
maximum_integrity_protected_data_rate_uplink);
return OGS_ERROR;
}
integrityProtectionIndication =
smf_integrity_protection_indication_value2enum(
self.security_indication.integrity_protection_indication);
if (integrityProtectionIndication ==
NGAP_IntegrityProtectionIndication_required ||
integrityProtectionIndication ==
NGAP_IntegrityProtectionIndication_preferred) {
} else {
ogs_error("Invalid security_indication [%s:UL-%s]",
self.security_indication.integrity_protection_indication ?
self.security_indication.integrity_protection_indication :
"No integrity_protection_indication",
self.security_indication.
maximum_integrity_protected_data_rate_uplink ?
self.security_indication.
maximum_integrity_protected_data_rate_uplink :
"No integrity_protection_indication");
return OGS_ERROR;
}
}
if (self.security_indication.maximum_integrity_protected_data_rate_downlink) {
if (smf_maximum_integrity_protected_data_rate_downlink_value2enum(
self.security_indication.
maximum_integrity_protected_data_rate_downlink) < 0) {
ogs_error("Invalid "
"maximum_integrity_protected_data_rate_downlink [%s]",
self.security_indication.
maximum_integrity_protected_data_rate_downlink);
return OGS_ERROR;
}
if (!self.security_indication.
maximum_integrity_protected_data_rate_uplink) {
ogs_error("No maximum_integrity_protected_data_rate_uplink");
return OGS_ERROR;
}
}
return OGS_OK;
}
@ -825,6 +902,40 @@ int smf_context_parse_config(void)
} while (ogs_yaml_iter_type(&info_array) ==
YAML_SEQUENCE_NODE);
} else if (!strcmp(smf_key, "security_indication")) {
ogs_yaml_iter_t security_indication_iter;
ogs_yaml_iter_recurse(
&smf_iter, &security_indication_iter);
while (ogs_yaml_iter_next(&security_indication_iter)) {
const char *security_indication_key =
ogs_yaml_iter_key(&security_indication_iter);
ogs_assert(security_indication_key);
if (!strcmp(security_indication_key,
"integrity_protection_indication")) {
self.security_indication.
integrity_protection_indication =
ogs_yaml_iter_value(
&security_indication_iter);
} else if (!strcmp(security_indication_key,
"confidentiality_protection_indication")) {
self.security_indication.
confidentiality_protection_indication =
ogs_yaml_iter_value(
&security_indication_iter);
} else if (!strcmp(security_indication_key,
"maximum_integrity_protected_data_rate_uplink")) {
self.security_indication.
maximum_integrity_protected_data_rate_uplink =
ogs_yaml_iter_value(
&security_indication_iter);
} else if (!strcmp(security_indication_key,
"maximum_integrity_protected_data_rate_downlink")) {
self.security_indication.
maximum_integrity_protected_data_rate_downlink =
ogs_yaml_iter_value(
&security_indication_iter);
}
}
} else if (!strcmp(smf_key, "pfcp")) {
/* handle config in pfcp library */
} else if (!strcmp(smf_key, "subnet")) {
@ -2981,3 +3092,42 @@ static void stats_remove_smf_session(void)
num_of_smf_sess = num_of_smf_sess - 1;
ogs_info("[Removed] Number of SMF-Sessions is now %d", num_of_smf_sess);
}
int smf_integrity_protection_indication_value2enum(const char *value)
{
ogs_assert(value);
if (!strcmp(value, "required"))
return NGAP_IntegrityProtectionIndication_required;
else if (!strcmp(value, "preferred"))
return NGAP_IntegrityProtectionIndication_preferred;
else if (!strcmp(value, "not-needed"))
return NGAP_IntegrityProtectionIndication_not_needed;
else {
ogs_error("Invalid value[%s]", value);
return -1;
}
}
int smf_confidentiality_protection_indication_value2enum(const char *value)
{
ogs_assert(value);
return smf_integrity_protection_indication_value2enum(value);
}
int smf_maximum_integrity_protected_data_rate_uplink_value2enum(
const char *value)
{
ogs_assert(value);
if (!strcmp(value, "bitrate64kbs"))
return NGAP_MaximumIntegrityProtectedDataRate_bitrate64kbs;
else if (!strcmp(value, "maximum-UE-rate"))
return NGAP_MaximumIntegrityProtectedDataRate_maximum_UE_rate;
else {
ogs_error("Invalid value[%s]", value);
return -1;
}
}
int smf_maximum_integrity_protected_data_rate_downlink_value2enum(
const char *value)
{
ogs_assert(value);
return smf_maximum_integrity_protected_data_rate_uplink_value2enum(value);
}

View File

@ -92,6 +92,13 @@ typedef struct smf_context_s {
uint16_t mtu; /* MTU to advertise in PCO */
struct {
const char *integrity_protection_indication;
const char *confidentiality_protection_indication;
const char *maximum_integrity_protected_data_rate_uplink;
const char *maximum_integrity_protected_data_rate_downlink;
} security_indication;
#define SMF_UE_IS_LAST_SESSION(__sMF) \
((__sMF) && (ogs_list_count(&(__sMF)->sess_list)) == 1)
ogs_list_t smf_ue_list;
@ -512,6 +519,13 @@ void smf_pf_identifier_pool_final(smf_bearer_t *bearer);
void smf_pf_precedence_pool_init(smf_sess_t *sess);
void smf_pf_precedence_pool_final(smf_sess_t *sess);
int smf_integrity_protection_indication_value2enum(const char *value);
int smf_confidentiality_protection_indication_value2enum(const char *value);
int smf_maximum_integrity_protected_data_rate_uplink_value2enum(
const char *value);
int smf_maximum_integrity_protected_data_rate_downlink_value2enum(
const char *value);
#ifdef __cplusplus
}
#endif

View File

@ -33,6 +33,7 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
NGAP_GTPTunnel_t *gTPTunnel = NULL;
NGAP_DataForwardingNotPossible_t *DataForwardingNotPossible = NULL;
NGAP_PDUSessionType_t *PDUSessionType = NULL;
NGAP_SecurityIndication_t *SecurityIndication = NULL;
NGAP_QosFlowSetupRequestList_t *QosFlowSetupRequestList = NULL;
NGAP_QosFlowSetupRequestItem_t *QosFlowSetupRequestItem = NULL;
NGAP_QosFlowIdentifier_t *qosFlowIdentifier = NULL;
@ -129,6 +130,89 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer(
ogs_assert_if_reached();
}
if (smf_self()->security_indication.integrity_protection_indication &&
smf_self()->security_indication.confidentiality_protection_indication) {
ie = CALLOC(1,
sizeof(NGAP_PDUSessionResourceSetupRequestTransferIEs_t));
ogs_assert(ie);
ASN_SEQUENCE_ADD(&message.protocolIEs, ie);
ie->id = NGAP_ProtocolIE_ID_id_SecurityIndication;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_PDUSessionResourceSetupRequestTransferIEs__value_PR_SecurityIndication;
SecurityIndication = &ie->value.choice.SecurityIndication;
SecurityIndication->integrityProtectionIndication =
smf_integrity_protection_indication_value2enum(
smf_self()->security_indication.
integrity_protection_indication);
ogs_assert(SecurityIndication->integrityProtectionIndication >= 0);
SecurityIndication->confidentialityProtectionIndication =
smf_confidentiality_protection_indication_value2enum(
smf_self()->security_indication.
confidentiality_protection_indication);
ogs_assert(SecurityIndication->
confidentialityProtectionIndication >= 0);
if (smf_self()->security_indication.
maximum_integrity_protected_data_rate_uplink) {
ogs_assert(
SecurityIndication->integrityProtectionIndication ==
NGAP_IntegrityProtectionIndication_required ||
SecurityIndication->integrityProtectionIndication ==
NGAP_IntegrityProtectionIndication_preferred);
SecurityIndication->maximumIntegrityProtectedDataRate_UL =
CALLOC(1, sizeof(NGAP_MaximumIntegrityProtectedDataRate_t));
ogs_assert(SecurityIndication->
maximumIntegrityProtectedDataRate_UL);
*(SecurityIndication->maximumIntegrityProtectedDataRate_UL) =
smf_maximum_integrity_protected_data_rate_uplink_value2enum(
smf_self()->security_indication.
maximum_integrity_protected_data_rate_uplink);
ogs_assert(
*(SecurityIndication->
maximumIntegrityProtectedDataRate_UL) >= 0);
if (smf_self()->security_indication.
maximum_integrity_protected_data_rate_downlink) {
NGAP_ProtocolExtensionContainer_9625P229_t *extContainer = NULL;
NGAP_SecurityIndication_ExtIEs_t *extIe = NULL;
NGAP_MaximumIntegrityProtectedDataRate_t
*MaximumIntegrityProtectedDataRate = NULL;
extContainer = CALLOC(1,
sizeof(NGAP_ProtocolExtensionContainer_9625P229_t));
ogs_assert(extContainer);
SecurityIndication->iE_Extensions =
(struct NGAP_ProtocolExtensionContainer *)extContainer;
extIe = CALLOC(1, sizeof(NGAP_SecurityIndication_ExtIEs_t));
ogs_assert(extIe);
ASN_SEQUENCE_ADD(&extContainer->list, extIe);
extIe->id =
NGAP_ProtocolIE_ID_id_MaximumIntegrityProtectedDataRate_DL;
extIe->criticality = NGAP_Criticality_ignore;
extIe->extensionValue.present = NGAP_SecurityIndication_ExtIEs__extensionValue_PR_MaximumIntegrityProtectedDataRate;
MaximumIntegrityProtectedDataRate =
&extIe->extensionValue.choice.
MaximumIntegrityProtectedDataRate;
*MaximumIntegrityProtectedDataRate =
smf_maximum_integrity_protected_data_rate_downlink_value2enum(
smf_self()->security_indication.
maximum_integrity_protected_data_rate_downlink);
ogs_assert(*MaximumIntegrityProtectedDataRate >= 0);
}
}
}
ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceSetupRequestTransferIEs_t));
ogs_assert(ie);
ASN_SEQUENCE_ADD(&message.protocolIEs, ie);