Add NAS Service Request enc/dec functions

* FGMM enc/dec library files
* Plain message encoding + logic for security protected message
* added fill_fgstmsi function
* add checks on length in 5G-S-TMSI encoder function
* encoding of NAS Service Request and relevant mandatory IEs
This commit is contained in:
Guido Casati
2024-11-25 13:15:10 +01:00
parent c817c44ae9
commit 1c4e1029a8
7 changed files with 317 additions and 0 deletions
@@ -0,0 +1,90 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "TLVEncoder.h"
#include "TLVDecoder.h"
#include "fgs_service_request.h"
#include "FGSMobileIdentity.h"
#include "NasKeySetIdentifier.h"
#include "ServiceType.h"
#include "NR_NAS_defs.h"
#define LEN_FGS_MOBILE_ID_CONTENTS_SIZE 2 // octets
#define MIN_LEN_FGS_SERVICE_REQUEST 10 // octets
/**
* @brief Encode 5GMM NAS Service Request message (8.2.16 of 3GPP TS 24.501)
*/
int encode_fgs_service_request(uint8_t *buffer, fgs_service_request_msg_t *service_request, uint32_t len)
{
// Return if buffer is shorter than min length
if (len < MIN_LEN_FGS_SERVICE_REQUEST)
return -1;
int encoded = 0;
// ngKSI + Service type (1 octet) (M)
*buffer = ((encode_nas_key_set_identifier(&service_request->naskeysetidentifier, IEI_NULL) & 0x0f) << 4)
| (service_request->serviceType & 0x0f);
encoded++;
len -= encoded;
// 5GS Mobile Identity (M) type 5G-S-TMSI (9 octets)
encoded += LEN_FGS_MOBILE_ID_CONTENTS_SIZE; // skip "Length of 5GS mobile identity contents" IE
len -= encoded;
encoded += encode_stmsi_5gs_mobile_identity(buffer + encoded, &service_request->fiveg_s_tmsi, len);
// encode length of 5GS mobile identity contents
uint16_t tmp = htons(encoded - LEN_FGS_MOBILE_ID_CONTENTS_SIZE - 1);
memcpy(buffer + 1, &tmp, sizeof(tmp));
return encoded;
}
/**
* @brief Decode 5GMM NAS Service Request message (8.2.16 of 3GPP TS 24.501)
*/
int decode_fgs_service_request(fgs_service_request_msg_t *sr, const uint8_t *buffer, uint32_t len)
{
uint32_t decoded = 0;
int decoded_rc = 0;
// Service type (1/2 octet) (M)
sr->serviceType = *buffer & 0x0f;
// KSI (1/2 octet) (M)
if ((decoded_rc = decode_nas_key_set_identifier(&sr->naskeysetidentifier, IEI_NULL, *buffer >> 4)) < 0) {
return decoded_rc;
}
decoded++;
// 5GS Mobile Identity (M) type 5G-S-TMSI (9 octets) (M)
decoded += LEN_FGS_MOBILE_ID_CONTENTS_SIZE; // skip "Length of 5GS mobile identity contents" IE
if ((decoded_rc = decode_stmsi_5gs_mobile_identity(&sr->fiveg_s_tmsi, buffer + decoded, len - decoded)) < 0) {
return decoded_rc;
}
decoded += decoded_rc;
return decoded;
}
@@ -0,0 +1,62 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "ProtocolDiscriminator.h"
#include "SecurityHeaderType.h"
#include "NasKeySetIdentifier.h"
#include "ServiceType.h"
#include "ExtendedProtocolDiscriminator.h"
#include "FGCNasMessageContainer.h"
//#include "PDUSessionStatus.h"
#include "MessageType.h"
#include "SpareHalfOctet.h"
#include "FGSMobileIdentity.h"
#ifndef FGS_SERVICE_REQUEST_H_
#define FGS_SERVICE_REQUEST_H_
/**
* Message name: Service request (8.2.16 of 3GPP TS 24.501)
* Description: The SERVICE REQUEST message is sent by the UE to the AMF
* in order to request the establishment of an N1 NAS signalling
* connection and/or to request the establishment of user-plane
* resources for PDU sessions which are established without
* user-plane resources
* Direction: UE to network
*/
typedef struct {
/* Mandatory fields */
NasKeySetIdentifier naskeysetidentifier;
ServiceType serviceType: 4;
Stmsi5GSMobileIdentity_t fiveg_s_tmsi;
/* Optional fields */
FGCNasMessageContainer *fgsnasmessagecontainer;
} fgs_service_request_msg_t;
int encode_fgs_service_request(uint8_t *buffer, fgs_service_request_msg_t *servicerequest, uint32_t len);
int decode_fgs_service_request(fgs_service_request_msg_t *sr, const uint8_t *buffer, uint32_t len);
#endif /* ! defined(FGS_SERVICE_REQUEST_H_) */
@@ -38,6 +38,7 @@
#include "FGSMobileIdentity.h"
#define MIN_LEN_FGS_MOBILE_ID_IE 3 // type of identity "No identity"
#define LEN_5G_FGS_TMSI_IE 9
static int decode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, const uint8_t *buffer);
@@ -45,6 +46,56 @@ static int encode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, uint8_
static int encode_suci_5gs_mobile_identity(Suci5GSMobileIdentity_t *suci, uint8_t *buffer);
static int encode_imeisv_5gs_mobile_identity(Imeisv5GSMobileIdentity_t *imeisv, uint8_t *buffer);
int encode_stmsi_5gs_mobile_identity(uint8_t *buffer, Stmsi5GSMobileIdentity_t *stmsi, uint32_t len)
{
// Return if buffer is shorter than min length
if (len < LEN_5G_FGS_TMSI_IE)
return -1;
uint32_t encoded = 0;
// octet 4
*(buffer + encoded) = (DIGIT1 << 4) | ((stmsi->spare & 0x1) << 3) | (stmsi->typeofidentity & 0x7);
encoded++;
// octet 5-6
uint16_t temp = 0x00 | ((stmsi->amfsetid) << 6) | (stmsi->amfpointer & 0x3f);
IES_ENCODE_U16(buffer, encoded, temp);
// octet 7
IES_ENCODE_U32(buffer, encoded, stmsi->tmsi);
return encoded;
}
int decode_stmsi_5gs_mobile_identity(Stmsi5GSMobileIdentity_t *stmsi, const uint8_t *buffer, uint32_t len)
{
int decoded = 0;
uint16_t temp;
// Return if buffer is shorter than min length
if (len < LEN_5G_FGS_TMSI_IE)
return -1;
// Octet 4: spare (bit 3) and type of identity (bits 0-2)
stmsi->digit1 = DIGIT1;
stmsi->spare = (*(buffer + decoded) >> 3) & 0x1;
stmsi->typeofidentity = *(buffer + decoded) & 0x7;
// Validate type of identity
if (stmsi->typeofidentity != FGS_MOBILE_IDENTITY_5GS_TMSI) {
return -1;
}
decoded++;
// Octet 5-6: AMF Set ID (bits 6-15) and AMF Pointer (bits 0-5)
IES_DECODE_U16(buffer, decoded, temp);
stmsi->amfsetid = (temp >> 6) & 0x03ff;
stmsi->amfpointer = temp & 0x3f;
// Octet 7-10: 32-bit TMSI
IES_DECODE_U32(buffer, decoded, stmsi->tmsi);
return decoded;
}
int decode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei, const uint8_t *buffer, uint32_t len)
{
int decoded_rc = TLV_DECODE_VALUE_DOESNT_MATCH;
@@ -109,6 +160,10 @@ int encode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei
buffer + encoded);
}
if (fgsmobileidentity->stmsi.typeofidentity == FGS_MOBILE_IDENTITY_5GS_TMSI) {
encoded_rc = encode_stmsi_5gs_mobile_identity(buffer + encoded, &fgsmobileidentity->stmsi, len);
}
if (encoded_rc < 0) {
return encoded_rc;
}
@@ -37,6 +37,8 @@
#ifndef FGS_MOBILE_IDENTITY_H_
#define FGS_MOBILE_IDENTITY_H_
// 4x 1bit according to 9.11.3.4 5GS mobile identity (type 5G-S-TMSI)
#define DIGIT1 0xF
typedef struct {
uint8_t spare:5;
@@ -151,5 +153,8 @@ int encode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei
int decode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei, const uint8_t *buffer, uint32_t len);
int encode_stmsi_5gs_mobile_identity(uint8_t *buffer, Stmsi5GSMobileIdentity_t *stmsi, uint32_t len);
int decode_stmsi_5gs_mobile_identity(Stmsi5GSMobileIdentity_t *stmsi, const uint8_t *buffer, uint32_t len);
#endif /* FGS MOBILE IDENTITY_H_ */