From 7f5fb1c9881cf846bc27bb75d9fe9d8edca510ca Mon Sep 17 00:00:00 2001
From: Lionel Gauthier <lionel.gauthier@eurecom.fr>
Date: Wed, 6 Aug 2014 20:04:43 +0000
Subject: [PATCH] Replayed ue security capabilities

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5675 818b1a75-f10b-46b9-bf7c-635c3b92a50f
---
 .../EURECOM-NAS/src/api/network/nas_message.c |  4 +-
 openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c   | 83 +++++++++++++++----
 .../EURECOM-NAS/src/emm/SecurityModeControl.c | 52 ++++++++----
 openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h  | 16 +++-
 openair-cn/NAS/EURECOM-NAS/src/emm/emm_main.c |  4 +-
 openair-cn/NAS/EURECOM-NAS/src/emm/emm_proc.h |  7 +-
 .../EURECOM-NAS/src/emm/msg/AttachRequest.c   |  3 +-
 .../NAS/EURECOM-NAS/src/emm/sap/emm_as.c      |  2 -
 .../NAS/EURECOM-NAS/src/emm/sap/emm_asDef.h   |  6 ++
 .../NAS/EURECOM-NAS/src/emm/sap/emm_recv.c    | 15 +++-
 .../NAS/EURECOM-NAS/src/emm/sap/emm_send.c    | 10 ++-
 .../EURECOM-NAS/src/ies/UeNetworkCapability.c | 43 +++++++---
 .../EURECOM-NAS/src/ies/UeNetworkCapability.h |  3 +
 .../src/ies/UeSecurityCapability.c            | 21 +++--
 .../src/ies/UeSecurityCapability.h            |  3 +-
 openair-cn/SGI/sgi_task.c                     |  2 -
 16 files changed, 203 insertions(+), 71 deletions(-)

diff --git a/openair-cn/NAS/EURECOM-NAS/src/api/network/nas_message.c b/openair-cn/NAS/EURECOM-NAS/src/api/network/nas_message.c
index 0961f33a90..8d8d4e9516 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/api/network/nas_message.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/api/network/nas_message.c
@@ -706,7 +706,7 @@ static int _nas_message_protected_decode(
 
     int bytes = TLV_DECODE_BUFFER_TOO_SHORT;
 
-    char* plain_msg = (char*)malloc(length);
+    char* plain_msg = (char*)calloc(1,length);
     if (plain_msg)
     {
         /* Decrypt the security protected NAS message */
@@ -862,7 +862,7 @@ static int _nas_message_protected_encode(
     emm_security_context_t *emm_security_context   = (emm_security_context_t*)security;
     int bytes = TLV_ENCODE_BUFFER_TOO_SHORT;
 
-    char* plain_msg = (char*)malloc(length);
+    char* plain_msg = (char*)calloc(1,length);
     if (plain_msg) {
         /* Encode the security protected NAS message as plain NAS message */
         int size = _nas_message_plain_encode(plain_msg, &msg->header,
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c b/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c
index bc3d3f5ac7..0cb19ad37d 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c
@@ -152,11 +152,14 @@ static int _emm_attach_abort(void *);
 static int _emm_attach_have_changed(const emm_data_context_t *ctx,
                                     emm_proc_attach_type_t type, int ksi,
                                     GUTI_t *guti, imsi_t *imsi, imei_t *imei,
-                                    int eea, int eia);
+                                    int eea, int eia, int ucs2, int uea, int uia, int gea,
+                                    int umts_present, int gprs_present);
 static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid,
                               emm_proc_attach_type_t type, int ksi,
                               GUTI_t *guti, imsi_t *imsi, imei_t *imei,
-                              int eea, int eia, const OctetString *esm_msg);
+                              int eea, int eia, int ucs2, int uea, int uia, int gea,
+                              int umts_present, int gprs_present,
+                              const OctetString *esm_msg);
 
 /*
  * Internal data used for attach procedure
@@ -286,10 +289,10 @@ int emm_proc_attach(emm_proc_attach_type_t type)
         if (_emm_data.security->type != EMM_KSI_NOT_AVAILABLE) {
             emm_as->ksi = _emm_data.security->eksi;
         }
-        LOG_TRACE(INFO, "EMM-PROC  - encryption 0x%X", _emm_data.security->capability.encryption);
-        LOG_TRACE(INFO, "EMM-PROC  - integrity  0x%X", _emm_data.security->capability.integrity);
-        emm_as->encryption = _emm_data.security->capability.encryption;
-        emm_as->integrity = _emm_data.security->capability.integrity;
+        LOG_TRACE(INFO, "EMM-PROC  - eps_encryption 0x%X", _emm_data.security->capability.eps_encryption);
+        LOG_TRACE(INFO, "EMM-PROC  - eps_integrity  0x%X", _emm_data.security->capability.eps_integrity);
+        emm_as->encryption = _emm_data.security->capability.eps_encryption;
+        emm_as->integrity = _emm_data.security->capability.eps_integrity;
     }
     /*
      * Notify ESM that initiation of a PDN connectivity procedure
@@ -1051,7 +1054,9 @@ int emm_proc_attach_set_detach(void)
 int emm_proc_attach_request(unsigned int ueid, emm_proc_attach_type_t type,
                             int native_ksi, int ksi, int native_guti,
                             GUTI_t *guti, imsi_t *imsi, imei_t *imei,
-                            tai_t *tai, int eea, int eia,
+                            tai_t *tai,
+                            int eea, int eia, int ucs2, int uea, int uia, int gea,
+                            int umts_present, int gprs_present,
                             const OctetString *esm_msg)
 {
     LOG_FUNC_IN;
@@ -1061,6 +1066,8 @@ int emm_proc_attach_request(unsigned int ueid, emm_proc_attach_type_t type,
 
     LOG_TRACE(INFO, "EMM-PROC  - EPS attach type = %s (%d) requested (ueid=0x%08x)",
               _emm_attach_type_str[type], type, ueid);
+    LOG_TRACE(INFO, "EMM-PROC  - umts_present = %u umts_present = %u",
+            umts_present, gprs_present);
 
     /* Initialize the temporary UE context */
     memset(&ue_ctx, 0 , sizeof(emm_data_context_t));
@@ -1105,7 +1112,7 @@ int emm_proc_attach_request(unsigned int ueid, emm_proc_attach_type_t type,
     if (*emm_ctx != NULL) {
         /* An EMM context already exists for the UE in the network */
         if (_emm_attach_have_changed(*emm_ctx, type, ksi, guti, imsi, imei,
-                                     eea, eia)) {
+                eea, eia, ucs2, uea, uia, gea, umts_present, gprs_present)) {
             /*
              * 3GPP TS 24.301, section 5.5.1.2.7, abnormal case e
              * The attach parameters have changed from the one received within
@@ -1129,7 +1136,8 @@ int emm_proc_attach_request(unsigned int ueid, emm_proc_attach_type_t type,
                 LOG_TRACE(WARNING, "EMM-PROC  - Initiate new attach procedure");
                 rc = emm_proc_attach_request(ueid, type, native_ksi, ksi,
                                              native_guti, guti, imsi, imei,
-                                             tai, eea, eia, esm_msg);
+                                             tai, eea, eia, ucs2, uea, uia, gea,
+                                             umts_present, gprs_present, esm_msg);
             }
             LOG_FUNC_RETURN(rc);
         } else {
@@ -1178,7 +1186,7 @@ int emm_proc_attach_request(unsigned int ueid, emm_proc_attach_type_t type,
 
     /* Update the EMM context with the current attach procedure parameters */
     rc = _emm_attach_update(*emm_ctx, ueid, type, ksi, guti, imsi, imei,
-                            eea, eia, esm_msg);
+            eea, eia, ucs2, uea, uia, gea, umts_present, gprs_present, esm_msg);
     if (rc != RETURNok) {
         LOG_TRACE(WARNING, "EMM-PROC  - Failed to update EMM context");
         /* Do not accept the UE to attach to the network */
@@ -2104,9 +2112,11 @@ static int _emm_attach_security(void *args)
 
     /* Initialize the security mode control procedure */
     rc = emm_proc_security_mode_control(emm_ctx->ueid, 0, // TODO: eksi != 0
-                                        emm_ctx->eea, emm_ctx->eia,
-                                        _emm_attach, _emm_attach_release,
-                                        _emm_attach_release);
+            emm_ctx->eea, emm_ctx->eia,emm_ctx->ucs2,
+            emm_ctx->uea, emm_ctx->uia, emm_ctx->gea,
+            emm_ctx->umts_present, emm_ctx->gprs_present,
+            _emm_attach, _emm_attach_release,
+            _emm_attach_release);
     if (rc != RETURNok) {
         /* Failed to initiate the security mode control procedure */
         LOG_TRACE(WARNING, "EMM-PROC  - "
@@ -2373,7 +2383,8 @@ static int _emm_attach_accept(emm_data_context_t *emm_ctx, attach_data_t *data)
 static int _emm_attach_have_changed(const emm_data_context_t *ctx,
                                     emm_proc_attach_type_t type, int ksi,
                                     GUTI_t *guti, imsi_t *imsi, imei_t *imei,
-                                    int eea, int eia)
+                                    int eea, int eia, int ucs2, int uea, int uia, int gea,
+                                    int umts_present, int gprs_present)
 {
     LOG_FUNC_IN;
     /* Emergency bearer services indicator */
@@ -2392,6 +2403,31 @@ static int _emm_attach_have_changed(const emm_data_context_t *ctx,
     if (eia != ctx->eia) {
         LOG_FUNC_RETURN (TRUE);
     }
+    if (umts_present != ctx->umts_present){
+        LOG_FUNC_RETURN (TRUE);
+    }
+    if (ctx->umts_present){
+        if (ucs2 != ctx->ucs2) {
+            LOG_FUNC_RETURN (TRUE);
+        }
+        /* Supported UMTS encryption algorithms */
+        if (uea != ctx->uea) {
+            LOG_FUNC_RETURN (TRUE);
+        }
+        /* Supported UMTS integrity algorithms */
+        if (uia != ctx->uia) {
+            LOG_FUNC_RETURN (TRUE);
+        }
+    }
+    if (gprs_present != ctx->gprs_present){
+        LOG_FUNC_RETURN (TRUE);
+    }
+    if (ctx->gprs_present){
+        if (gea != ctx->gea) {
+            LOG_FUNC_RETURN (TRUE);
+        }
+    }
+
     /* The GUTI if provided by the UE */
     if ( (guti) && (ctx->guti == NULL) ) {
         LOG_FUNC_RETURN (TRUE);
@@ -2461,7 +2497,9 @@ static int _emm_attach_have_changed(const emm_data_context_t *ctx,
 static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid,
                               emm_proc_attach_type_t type, int ksi,
                               GUTI_t *guti, imsi_t *imsi, imei_t *imei,
-                              int eea, int eia, const OctetString *esm_msg)
+                              int eea, int eia, int ucs2, int uea, int uia, int gea,
+                              int umts_present, int gprs_present,
+                              const OctetString *esm_msg)
 {
     LOG_FUNC_IN;
     /* UE identifier */
@@ -2469,11 +2507,20 @@ static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid,
     /* Emergency bearer services indicator */
     ctx->is_emergency = (type == EMM_ATTACH_TYPE_EMERGENCY);
     /* Security key set identifier */
-    ctx->ksi = ksi;
+    ctx->ksi  = ksi;
     /* Supported EPS encryption algorithms */
-    ctx->eea = eea;
+    ctx->eea  = eea;
     /* Supported EPS integrity algorithms */
-    ctx->eia = eia;
+    ctx->eia  = eia;
+    ctx->ucs2 = ucs2;
+    ctx->uea  = uea;
+    ctx->uia  = uia;
+    ctx->gea  = gea;
+    LOG_TRACE(WARNING, "EMM-PROC  - umts_present %u", umts_present);
+    LOG_TRACE(WARNING, "EMM-PROC  - gprs_present %u", gprs_present);
+    ctx->umts_present  = umts_present;
+    ctx->gprs_present  = gprs_present;
+
     /* The GUTI if provided by the UE */
     if (guti) {
         if (ctx->guti == NULL) {
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/SecurityModeControl.c b/openair-cn/NAS/EURECOM-NAS/src/emm/SecurityModeControl.c
index 4d941cc997..9aa4a2cc51 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/SecurityModeControl.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/SecurityModeControl.c
@@ -133,14 +133,20 @@ static int _security_select_algorithms(
  * Internal data used for security mode control procedure
  */
 typedef struct {
-    unsigned int ueid;      /* UE identifier                       */
+    unsigned int ueid;      /* UE identifier                         */
 #define SECURITY_COUNTER_MAX    5
-    unsigned int retransmission_count;  /* Retransmission counter   */
-    int ksi;                /* NAS key set identifier               */
-    int eea;                /* Replayed EPS encryption algorithms   */
-    int eia;                /* Replayed EPS integrity algorithms    */
-    int selected_eea;       /* Selected EPS encryption algorithms   */
-    int selected_eia;       /* Selected EPS integrity algorithms    */
+    unsigned int retransmission_count;  /* Retransmission counter    */
+    int ksi;                /* NAS key set identifier                */
+    int eea;                /* Replayed EPS encryption algorithms    */
+    int eia;                /* Replayed EPS integrity algorithms     */
+    int ucs2;               /* Replayed Alphabet                     */
+    int uea;                /* Replayed UMTS encryption algorithms   */
+    int uia;                /* Replayed UMTS integrity algorithms    */
+    int gea;                /* Replayed G encryption algorithms      */
+    int umts_present:1;
+    int gprs_present:1;
+    int selected_eea;       /* Selected EPS encryption algorithms    */
+    int selected_eia;       /* Selected EPS integrity algorithms     */
     int notify_failure;     /* Indicates whether the security mode control
                              * procedure failure shall be notified to the
                              * ongoing EMM procedure        */
@@ -206,8 +212,8 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
     /*
      * Check the replayed UE security capabilities
      */
-    UInt8_t eea = (0x80 >> _emm_data.security->capability.encryption);
-    UInt8_t eia = (0x80 >> _emm_data.security->capability.integrity);
+    UInt8_t eea = (0x80 >> _emm_data.security->capability.eps_encryption);
+    UInt8_t eia = (0x80 >> _emm_data.security->capability.eps_integrity);
     if ( (reea != eea) || (reia != eia) ) {
         LOG_TRACE(WARNING, "EMM-PROC  - Replayed UE security capabilities "
                   "rejected");
@@ -412,10 +418,11 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
-                                   emm_common_success_callback_t success,
-                                   emm_common_reject_callback_t reject,
-                                   emm_common_failure_callback_t failure)
+int emm_proc_security_mode_control(unsigned int ueid, int ksi,
+        int eea, int eia,int ucs2, int uea, int uia, int gea, int umts_present, int gprs_present,
+        emm_common_success_callback_t success,
+        emm_common_reject_callback_t reject,
+        emm_common_failure_callback_t failure)
 {
     int rc = RETURNerror;
     int security_context_is_new = FALSE;
@@ -536,9 +543,18 @@ int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
         data->eea = eea;
         /* Set the EPS integrity algorithms to be replayed to the UE */
         data->eia = eia;
-        /* Set the EPS encryption algorithms to be replayed to the UE */
+        data->ucs2 = ucs2;
+        /* Set the UMTS encryption algorithms to be replayed to the UE */
+        data->uea = uea;
+        /* Set the UMTS integrity algorithms to be replayed to the UE */
+        data->uia = uia;
+        /* Set the GPRS integrity algorithms to be replayed to the UE */
+        data->gea = gea;
+        data->umts_present = umts_present;
+        data->gprs_present = gprs_present;
+        /* Set the EPS encryption algorithms selected to the UE */
         data->selected_eea = emm_ctx->security->selected_algorithms.encryption;
-        /* Set the EPS integrity algorithms to be replayed to the UE */
+        /* Set the EPS integrity algorithms selected to the UE */
         data->selected_eia = emm_ctx->security->selected_algorithms.integrity;
         /* Set the failure notification indicator */
         data->notify_failure = FALSE;
@@ -1017,6 +1033,12 @@ int _security_request(security_data_t *data, int is_new)
     emm_sap.u.emm_as.u.security.ksi          = data->ksi;
     emm_sap.u.emm_as.u.security.eea          = data->eea;
     emm_sap.u.emm_as.u.security.eia          = data->eia;
+    emm_sap.u.emm_as.u.security.ucs2         = data->ucs2;
+    emm_sap.u.emm_as.u.security.uea          = data->uea;
+    emm_sap.u.emm_as.u.security.uia          = data->uia;
+    emm_sap.u.emm_as.u.security.gea          = data->gea;
+    emm_sap.u.emm_as.u.security.umts_present = data->umts_present;
+    emm_sap.u.emm_as.u.security.gprs_present = data->gprs_present;
     emm_sap.u.emm_as.u.security.selected_eea = data->selected_eea;
     emm_sap.u.emm_as.u.security.selected_eia = data->selected_eia;
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h b/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h
index 29c72c6884..283a6a64f2 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h
@@ -135,8 +135,13 @@ typedef struct {
         UInt32_t seq_num:8;
     } dl_count, ul_count;   /* Downlink and uplink count parameters    */
     struct {
-        UInt8_t encryption:4;   /* algorithm used for ciphering        */
-        UInt8_t integrity:4;    /* algorithm used for integrity protection */
+        UInt8_t eps_encryption;   /* algorithm used for ciphering            */
+        UInt8_t eps_integrity;    /* algorithm used for integrity protection */
+        UInt8_t umts_encryption;  /* algorithm used for ciphering            */
+        UInt8_t umts_integrity;   /* algorithm used for integrity protection */
+        UInt8_t gprs_encryption;  /* algorithm used for ciphering            */
+        UInt8_t umts_present:1;
+        UInt8_t gprs_present:1;
     } capability;       /* UE network capability           */
     struct {
         UInt8_t encryption:4;   /* algorithm used for ciphering           */
@@ -373,6 +378,13 @@ typedef struct emm_data_context_s {
     int         ksi;          /* Security key set identifier provided by the UE  */
     int         eea;          /* EPS encryption algorithms supported by the UE   */
     int         eia;          /* EPS integrity algorithms supported by the UE    */
+    int         ucs2;         /* UCS2 Alphabet*/
+    int         uea;          /* UMTS encryption algorithms supported by the UE  */
+    int         uia;          /* UMTS integrity algorithms supported by the UE   */
+    int         gea;          /* GPRS encryption algorithms supported by the UE  */
+    int         umts_present; /* For encoding ue network capabilities (variable size)*/
+    int         gprs_present; /* For encoding ue network capabilities (variable size)*/
+
     auth_vector_t vector;/* EPS authentication vector                            */
     emm_security_context_t *security;    /* Current EPS NAS security context     */
     OctetString esm_msg;      /* ESM message contained within the initial request*/
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/emm_main.c b/openair-cn/NAS/EURECOM-NAS/src/emm/emm_main.c
index 209313daa4..43aefec960 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/emm_main.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/emm_main.c
@@ -301,10 +301,10 @@ void emm_main_initialize(emm_indication_callback_t cb, const char *imei)
                        _usim_data.securityctx.ulNAScount.length);
             }
             /* Ciphering algorithm */
-            _emm_data.security->capability.encryption =
+            _emm_data.security->capability.eps_encryption =
                 ((_usim_data.securityctx.algorithmID.value[0] >> 4) & 0xf);
             /* Identity protection algorithm */
-            _emm_data.security->capability.integrity =
+            _emm_data.security->capability.eps_integrity =
                 (_usim_data.securityctx.algorithmID.value[0] & 0xf);
             /* NAS integrity and cyphering keys are not available */
         } else {
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/emm_proc.h b/openair-cn/NAS/EURECOM-NAS/src/emm/emm_proc.h
index 579f89e0fb..98fb511e7c 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/emm_proc.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/emm_proc.h
@@ -159,7 +159,8 @@ int emm_proc_attach_set_detach(void);
 #ifdef NAS_MME
 int emm_proc_attach_request(unsigned int ueid, emm_proc_attach_type_t type,
                             int native_ksi, int ksi, int native_guti, GUTI_t *guti, imsi_t *imsi,
-                            imei_t *imei, tai_t *tai, int eea, int eia, const OctetString *esm_msg);
+                            imei_t *imei, tai_t *tai, int eea, int eia, int ucs2, int uea, int uia, int gea,
+                            int umts_present, int gprs_present, const OctetString *esm_msg);
 int emm_proc_attach_reject(unsigned int ueid, int emm_cause);
 int emm_proc_attach_complete(unsigned int ueid, const OctetString *esm_msg);
 int emm_proc_tracking_area_update_reject(unsigned int ueid, int emm_cause);
@@ -240,7 +241,9 @@ int emm_proc_security_mode_command(int native_ksi, int ksi, int seea, int seia,
 #endif
 
 #ifdef NAS_MME
-int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
+int emm_proc_security_mode_control(unsigned int ueid, int ksi,
+                                   int eea, int eia,int ucs2, int uea, int uia, int gea,
+                                   int umts_present, int gprs_present,
                                    emm_common_success_callback_t success,
                                    emm_common_reject_callback_t reject,
                                    emm_common_failure_callback_t failure);
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/msg/AttachRequest.c b/openair-cn/NAS/EURECOM-NAS/src/emm/msg/AttachRequest.c
index 9ffd7b8f05..c5ecc4d540 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/msg/AttachRequest.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/msg/AttachRequest.c
@@ -43,7 +43,8 @@ int decode_attach_request(attach_request_msg *attach_request, uint8_t *buffer, u
     int decoded_result = 0;
 
     LOG_FUNC_IN;
-
+    LOG_TRACE(INFO, "EMM  - attach_request len = %d",
+            len);
     // Check if we got a NULL pointer and if buffer length is >= minimum length expected for the message.
     CHECK_PDU_POINTER_AND_LENGTH_DECODER(buffer, ATTACH_REQUEST_MINIMUM_LENGTH, len);
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_as.c b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_as.c
index f8788815ff..5abc62eccc 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_as.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_as.c
@@ -2037,8 +2037,6 @@ static int _emm_as_establish_cnf(const emm_as_establish_t *msg,
 
             as_msg->selected_encryption_algorithm = htons(0x8000 >> emm_security_context->selected_algorithms.encryption);
             as_msg->selected_integrity_algorithm = htons(0x8000 >> emm_security_context->selected_algorithms.integrity);
-            //as_msg->selected_encryption_algorithm = htons(0x8000 >> emm_security_context->capability.encryption);
-            //as_msg->selected_integrity_algorithm = htons(0x8000 >> emm_security_context->capability.integrity);
 
             LOG_TRACE(DEBUG,
                 "Set nas_msg.selected_encryption_algorithm -> NBO: 0x%04X (%u)",
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_asDef.h b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_asDef.h
index ad57f704d6..d20cea86d0 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_asDef.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_asDef.h
@@ -123,6 +123,12 @@ typedef struct {
      */
     UInt8_t eea;        /* Replayed EPS encryption algorithms   */
     UInt8_t eia;        /* Replayed EPS integrity algorithms    */
+    UInt8_t uea;        /* Replayed UMTS encryption algorithms  */
+    uint8_t ucs2;
+    UInt8_t uia;        /* Replayed UMTS integrity algorithms   */
+    UInt8_t gea;        /* Replayed GPRS encryption algorithms   */
+    UInt8_t umts_present;
+    UInt8_t gprs_present;
 
     // Added by LG
     UInt8_t selected_eea; /* Selected EPS encryption algorithms   */
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_recv.c b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_recv.c
index 490e543f14..9c16e2db3b 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_recv.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_recv.c
@@ -624,7 +624,20 @@ int emm_recv_attach_request(unsigned int ueid, const attach_request_msg *msg,
                                  msg->naskeysetidentifier.tsc != NAS_KEY_SET_IDENTIFIER_MAPPED,
                                  msg->naskeysetidentifier.naskeysetidentifier,
                                  msg->oldgutitype != GUTI_MAPPED, p_guti, p_imsi, p_imei, p_tai,
-                                 msg->uenetworkcapability.eea, msg->uenetworkcapability.eia,
+                                 msg->uenetworkcapability.eea,
+                                 msg->uenetworkcapability.eia,
+                                 msg->uenetworkcapability.ucs2,
+                                 msg->uenetworkcapability.uea,
+                                 msg->uenetworkcapability.uia,
+                                 0x00 |
+                                       //((msg->uenetworkcapability.spare & 0x7) << 5) | // spare coded as zero
+                                 ((msg->uenetworkcapability.csfb  & 0x1) << 4) |
+                                 ((msg->uenetworkcapability.lpp   & 0x1) << 3) |
+                                 ((msg->uenetworkcapability.lcs   & 0x1) << 2) |
+                                 ((msg->uenetworkcapability.srvcc & 0x1) << 1) |
+                                 (msg->uenetworkcapability.nf     & 0x1),
+                                 msg->uenetworkcapability.umts_present,
+                                 msg->uenetworkcapability.gprs_present,
                                  &msg->esmmessagecontainer.esmmessagecontainercontents);
 
     LOG_FUNC_RETURN (rc);
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_send.c b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_send.c
index f2efc199f9..8a0772d13d 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_send.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_send.c
@@ -1244,10 +1244,12 @@ int emm_send_security_mode_command(const emm_as_security_t *msg,
     size += UE_SECURITY_CAPABILITY_MAXIMUM_LENGTH;
     emm_msg->replayeduesecuritycapabilities.eea = msg->eea;
     emm_msg->replayeduesecuritycapabilities.eia = msg->eia;
-    emm_msg->replayeduesecuritycapabilities.non_eps_security_present = 0;
-    emm_msg->replayeduesecuritycapabilities.uea = 0x00;
-    emm_msg->replayeduesecuritycapabilities.uia = 0x00;
-    emm_msg->replayeduesecuritycapabilities.gea = 0x00;
+    emm_msg->replayeduesecuritycapabilities.umts_present = msg->umts_present;
+    emm_msg->replayeduesecuritycapabilities.gprs_present = msg->gprs_present;
+
+    emm_msg->replayeduesecuritycapabilities.uea = msg->uea;
+    emm_msg->replayeduesecuritycapabilities.uia = msg->uia;
+    emm_msg->replayeduesecuritycapabilities.gea = msg->gea;
 
     LOG_FUNC_RETURN (size);
 }
diff --git a/openair-cn/NAS/EURECOM-NAS/src/ies/UeNetworkCapability.c b/openair-cn/NAS/EURECOM-NAS/src/ies/UeNetworkCapability.c
index 2f2f606fb8..134e890278 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/ies/UeNetworkCapability.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/ies/UeNetworkCapability.c
@@ -29,6 +29,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <string.h>
 
 
 #include "TLVEncoder.h"
@@ -46,6 +47,8 @@ int decode_ue_network_capability(UeNetworkCapability *uenetworkcapability, uint8
     }
     DECODE_U8(buffer + decoded, ielen, decoded);
 
+    memset(uenetworkcapability, 0, sizeof(UeNetworkCapability));
+
     LOG_TRACE(INFO, "decode_ue_network_capability len = %d",ielen);
     CHECK_LENGTH_DECODER(len - decoded, ielen);
     uenetworkcapability->eea = *(buffer + decoded);
@@ -62,6 +65,8 @@ int decode_ue_network_capability(UeNetworkCapability *uenetworkcapability, uint8
             uenetworkcapability->ucs2 = (*(buffer + decoded) >> 7) & 0x1;
             uenetworkcapability->uia = *(buffer + decoded) & 0x7f;
             decoded++;
+            uenetworkcapability->umts_present =1;
+            LOG_TRACE(INFO, "uenetworkcapability decoded UMTS\n");
 
             if (ielen > 4) {
                 uenetworkcapability->spare = (*(buffer + decoded) >> 5) & 0x7;
@@ -71,6 +76,8 @@ int decode_ue_network_capability(UeNetworkCapability *uenetworkcapability, uint8
                 uenetworkcapability->srvcc = (*(buffer + decoded) >> 1) & 0x1;
                 uenetworkcapability->nf    = *(buffer + decoded) & 0x1;
                 decoded++;
+                uenetworkcapability->gprs_present =1;
+                LOG_TRACE(INFO, "uenetworkcapability decoded GPRS\n");
             }
         }
     }
@@ -106,20 +113,28 @@ int encode_ue_network_capability(UeNetworkCapability *uenetworkcapability, uint8
     encoded++;
     *(buffer + encoded) = uenetworkcapability->eia;
     encoded++;
-    *(buffer + encoded) = uenetworkcapability->uea;
-    encoded++;
-    *(buffer + encoded) = 0x00 | ((uenetworkcapability->ucs2 & 0x1) << 7) |
-    (uenetworkcapability->uia & 0x7f);
-    encoded++;
+    LOG_TRACE(INFO, "uenetworkcapability encoded EPS %u\n", encoded);
 
-    *(buffer + encoded) = 0x00 |
-	//((uenetworkcapability->spare & 0x7) << 5) | // spare coded as zero
-	((uenetworkcapability->csfb  & 0x1) << 4) |
-	((uenetworkcapability->lpp   & 0x1) << 3) |
-	((uenetworkcapability->lcs   & 0x1) << 2) |
-	((uenetworkcapability->srvcc & 0x1) << 1) |
-	(uenetworkcapability->nf     & 0x1);
-    encoded++;
+    if (uenetworkcapability->umts_present) {
+        *(buffer + encoded) = uenetworkcapability->uea;
+        encoded++;
+        *(buffer + encoded) = 0x00 | ((uenetworkcapability->ucs2 & 0x1) << 7) |
+                (uenetworkcapability->uia & 0x7f);
+        encoded++;
+        LOG_TRACE(INFO, "uenetworkcapability encoded UMTS %u\n", encoded);
+    }
+
+    if (uenetworkcapability->gprs_present) {
+        *(buffer + encoded) = 0x00 |
+                //((uenetworkcapability->spare & 0x7) << 5) | // spare coded as zero
+                ((uenetworkcapability->csfb  & 0x1) << 4) |
+                ((uenetworkcapability->lpp   & 0x1) << 3) |
+                ((uenetworkcapability->lcs   & 0x1) << 2) |
+                ((uenetworkcapability->srvcc & 0x1) << 1) |
+                (uenetworkcapability->nf     & 0x1);
+        encoded++;
+        LOG_TRACE(INFO, "uenetworkcapability encoded GPRS %u\n", encoded);
+    }
 
     *lenPtr = encoded - 1 - ((iei > 0) ? 1 : 0);
     return encoded;
@@ -142,6 +157,8 @@ void dump_ue_network_capability_xml(UeNetworkCapability *uenetworkcapability, ui
     printf("    <LCS>%u</LCS>\n", uenetworkcapability->lcs);
     printf("    <SR VCC>%u</SR VCC>\n", uenetworkcapability->srvcc);
     printf("    <NF>%u<NF/>\n", uenetworkcapability->nf);
+    printf("    <UMTS>%u<UMTS/>\n", uenetworkcapability->umts_present);
+    printf("    <GPRS>%u<GPRS/>\n", uenetworkcapability->gprs_present);
     printf("</Ue Network Capability>\n");
 }
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/ies/UeNetworkCapability.h b/openair-cn/NAS/EURECOM-NAS/src/ies/UeNetworkCapability.h
index c88ac2d6b9..e79a68820e 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/ies/UeNetworkCapability.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/ies/UeNetworkCapability.h
@@ -99,6 +99,9 @@ typedef struct UeNetworkCapability_tag {
     /* NF notification procedure capability */
 #define UE_NETWORK_CAPABILITY_NF	1
     uint8_t  nf:1;
+
+    uint8_t  umts_present;
+    uint8_t  gprs_present;
 } UeNetworkCapability;
 
 int encode_ue_network_capability(UeNetworkCapability *uenetworkcapability, uint8_t iei, uint8_t *buffer, uint32_t len);
diff --git a/openair-cn/NAS/EURECOM-NAS/src/ies/UeSecurityCapability.c b/openair-cn/NAS/EURECOM-NAS/src/ies/UeSecurityCapability.c
index 9672cbb40a..a3caa0a97a 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/ies/UeSecurityCapability.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/ies/UeSecurityCapability.c
@@ -29,6 +29,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <string.h>
 
 
 #include "TLVEncoder.h"
@@ -44,6 +45,7 @@ int decode_ue_security_capability(UeSecurityCapability *uesecuritycapability, ui
         CHECK_IEI_DECODER(iei, *buffer);
         decoded++;
     }
+    memset(uesecuritycapability, 0, sizeof(UeSecurityCapability));
     ielen = *(buffer + decoded);
     decoded++;
     CHECK_LENGTH_DECODER(len - decoded, ielen);
@@ -51,14 +53,17 @@ int decode_ue_security_capability(UeSecurityCapability *uesecuritycapability, ui
     decoded++;
     uesecuritycapability->eia = *(buffer + decoded);
     decoded++;
-    if (len == decoded + 3) {
-        uesecuritycapability->non_eps_security_present = 1;
+    if (len >= decoded + 3) {
+        uesecuritycapability->umts_present = 1;
         uesecuritycapability->uea = *(buffer + decoded);
         decoded++;
         uesecuritycapability->uia = *(buffer + decoded) & 0x7f;
         decoded++;
-        uesecuritycapability->gea = *(buffer + decoded) & 0x7f;
-        decoded++;
+        if (len == decoded + 4) {
+            uesecuritycapability->gprs_present = 1;
+            uesecuritycapability->gea = *(buffer + decoded) & 0x7f;
+            decoded++;
+        }
     }
 #if defined (NAS_DEBUG)
     dump_ue_security_capability_xml(uesecuritycapability, iei);
@@ -85,12 +90,14 @@ int encode_ue_security_capability(UeSecurityCapability *uesecuritycapability, ui
     encoded++;
     *(buffer + encoded) =  uesecuritycapability->eia;
     encoded++;
-    if (uesecuritycapability->non_eps_security_present == 1) {
+    if (uesecuritycapability->umts_present) {
         *(buffer + encoded) = uesecuritycapability->uea;
         encoded++;
         *(buffer + encoded) = 0x00 |
         (uesecuritycapability->uia & 0x7f);
         encoded++;
+    }
+    if (uesecuritycapability->gprs_present) {
         *(buffer + encoded) = 0x00 |
         (uesecuritycapability->gea & 0x7f);
         encoded++;
@@ -107,9 +114,11 @@ void dump_ue_security_capability_xml(UeSecurityCapability *uesecuritycapability,
         printf("    <IEI>0x%X</IEI>\n", iei);
     printf("    <EEA>%u</EEA>\n", uesecuritycapability->eea);
     printf("    <EIA>%u</EIA>\n", uesecuritycapability->eia);
-    if (uesecuritycapability->non_eps_security_present == 1) {
+    if (uesecuritycapability->umts_present == 1) {
         printf("    <UEA>%u</UEA>\n", uesecuritycapability->uea);
         printf("    <UIA>%u</UIA>\n", uesecuritycapability->uia);
+    }
+    if (uesecuritycapability->gprs_present == 1) {
         printf("    <GEA>%u</GEA>\n", uesecuritycapability->gea);
     }
     printf("</Ue Security Capability>\n");
diff --git a/openair-cn/NAS/EURECOM-NAS/src/ies/UeSecurityCapability.h b/openair-cn/NAS/EURECOM-NAS/src/ies/UeSecurityCapability.h
index 1b7e27ddcc..7f08a149c3 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/ies/UeSecurityCapability.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/ies/UeSecurityCapability.h
@@ -59,7 +59,8 @@ typedef struct UeSecurityCapability_tag {
 #define UE_SECURITY_CAPABILITY_EIA6	0b00000010
 #define UE_SECURITY_CAPABILITY_EIA7	0b00000001
     uint8_t  eia;
-    unsigned non_eps_security_present:1;
+    uint8_t  umts_present;
+    uint8_t  gprs_present;
     /* UMTS encryption algorithms supported (octet 5) */
 #define UE_SECURITY_CAPABILITY_UEA0	0b10000000
 #define UE_SECURITY_CAPABILITY_UEA1	0b01000000
diff --git a/openair-cn/SGI/sgi_task.c b/openair-cn/SGI/sgi_task.c
index 3fe9034644..7ca731c88a 100644
--- a/openair-cn/SGI/sgi_task.c
+++ b/openair-cn/SGI/sgi_task.c
@@ -281,7 +281,6 @@ int sgi_init(const pgw_config_t *pgw_config_p)
             return -1;
         }
 #endif
-#if 0
 #ifdef ENABLE_USE_RAW_SOCKET_FOR_SGI
         for (i=0; i < SGI_MAX_EPS_BEARERS_PER_USER; i++) {
             sgi_read_thread_args_t *args_p = malloc(sizeof(sgi_read_thread_args_t));
@@ -292,7 +291,6 @@ int sgi_init(const pgw_config_t *pgw_config_p)
                 return -1;
             }
         }
-#endif
 #endif
     }
 
-- 
GitLab