From 2f232889aea97c88d1a9891ec1a101894b7df2d6 Mon Sep 17 00:00:00 2001
From: Laurent THOMAS <laurent.thomas@open-cells.com>
Date: Wed, 10 Apr 2024 12:02:34 +0200
Subject: [PATCH] synchronous work between PDCP and RRC for DCCCH messages

---
 cmake_targets/build_oai                   |   2 +-
 openair2/COMMON/pdcp_messages_def.h       |   5 +-
 openair2/COMMON/pdcp_messages_types.h     |  18 ++
 openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c  |   2 +-
 openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 112 ++++++----
 openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h |  13 +-
 openair2/RRC/NR/nr_rrc_common.h           |   2 +-
 openair2/RRC/NR_UE/rrc_UE.c               | 239 +++++++++++-----------
 8 files changed, 222 insertions(+), 171 deletions(-)

diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai
index 5594b856afb..42317728f9c 100755
--- a/cmake_targets/build_oai
+++ b/cmake_targets/build_oai
@@ -510,7 +510,7 @@ function main() {
     # e.g., cmake_targets/ran_build/build, hence the ../../..
     CMAKE_CMD="$CMAKE_CMD ../../.."
     echo_info "Running \"$CMAKE_CMD\""
-    eval $CMAKE_CMD
+    $CMAKE_CMD
     compilations $BUILD_DIR all.txt $TARGET_LIST
     ###################
     # Doxygen Support #
diff --git a/openair2/COMMON/pdcp_messages_def.h b/openair2/COMMON/pdcp_messages_def.h
index 5392c9e04df..a9b7b940420 100644
--- a/openair2/COMMON/pdcp_messages_def.h
+++ b/openair2/COMMON/pdcp_messages_def.h
@@ -35,5 +35,6 @@ MESSAGE_DEF(RRC_NRUE_CAP_INFO_IND,      MESSAGE_PRIORITY_MED_PLUS, RrcDcchDataIn
 MESSAGE_DEF(RRC_DCCH_DATA_COPY_IND,     MESSAGE_PRIORITY_MED_PLUS, RrcDcchDataInd,         rrc_dcch_data_copy_ind)
 
 // gNB
-MESSAGE_DEF(NR_RRC_DCCH_DATA_REQ,       MESSAGE_PRIORITY_MED_PLUS, NRRrcDcchDataReq,           nr_rrc_dcch_data_req)
-MESSAGE_DEF(NR_RRC_DCCH_DATA_IND,       MESSAGE_PRIORITY_MED_PLUS, NRRrcDcchDataInd,           nr_rrc_dcch_data_ind)
+MESSAGE_DEF(NR_RRC_DCCH_DATA_REQ, MESSAGE_PRIORITY_MED_PLUS, NRRrcDcchDataReq, nr_rrc_dcch_data_req)
+MESSAGE_DEF(NR_RRC_DCCH_DATA_IND, MESSAGE_PRIORITY_MED_PLUS, NRRrcDcchDataInd, nr_rrc_dcch_data_ind)
+MESSAGE_DEF(NR_RRC_DCCH_DATA_RESP, MESSAGE_PRIORITY_MED_PLUS, RrcDcchDataResp, nr_rrc_dcch_data_resp)
diff --git a/openair2/COMMON/pdcp_messages_types.h b/openair2/COMMON/pdcp_messages_types.h
index b97fdef9861..f64147c011c 100644
--- a/openair2/COMMON/pdcp_messages_types.h
+++ b/openair2/COMMON/pdcp_messages_types.h
@@ -55,8 +55,25 @@ typedef struct RrcDcchDataReq_s {
   uint16_t     rnti;
   uint8_t      module_id;
   uint8_t eNB_index;
+  int returnTask; // itti circular include, impossible to use the correct enum
 } RrcDcchDataReq;
 
+#include "openair2/RRC/NR/nr_rrc_common.h"
+#define maxMSGs (10)
+#define maxSZ (maxMSGs * 100)
+typedef struct RrcDcchDataResp_s {
+  bool doCyphering;
+  bool doIntegrity;
+  uint8_t integrityProtAlgorithm;
+  uint8_t cipheringAlgorithm;
+  uint8_t kRRCenc[NR_K_KEY_SIZE];
+  uint8_t kUPenc[NR_K_KEY_SIZE];
+  uint8_t kRRCint[NR_K_KEY_SIZE];
+  int srbID;
+  uint8_t buffer[maxSZ];
+  int sz[maxMSGs];
+} RrcDcchDataResp;
+
 typedef struct RrcDcchDataInd_s {
   uint32_t frame;
   uint8_t dcch_index;
@@ -100,6 +117,7 @@ typedef struct NRRrcDcchDataInd_s {
   uint8_t gNB_index; // LG: needed in UE
   /* 'msg_integrity' is needed for RRC to check integrity of the PDCP SDU */
   nr_pdcp_integrity_data_t msg_integrity;
+  bool integrityResult;
 } NRRrcDcchDataInd;
 
 typedef struct RrcPcchDataReq_s {
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c
index 712bbf6b0cc..6d0be065e3f 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c
@@ -308,7 +308,7 @@ static bool nr_pdcp_entity_check_integrity(struct nr_pdcp_entity_t *entity,
                                            const nr_pdcp_integrity_data_t *msg_integrity)
 {
   if (!entity->has_integrity)
-    return false;
+    return true;
 
   int header_size = msg_integrity->header_size;
 
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
index 17b1b024080..fa71aa99077 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c
@@ -777,12 +777,53 @@ srb_found:
     memcpy(rrc_buffer_p, buf, size);
     MessageDef *message_p = itti_alloc_new_message(TASK_PDCP_UE, 0, NR_RRC_DCCH_DATA_IND);
     AssertFatal(message_p != NULL, "OUT OF MEMORY\n");
-    NR_RRC_DCCH_DATA_IND(message_p).dcch_index = srb_id;
-    NR_RRC_DCCH_DATA_IND(message_p).sdu_p = rrc_buffer_p;
-    NR_RRC_DCCH_DATA_IND(message_p).sdu_size = size;
-    memcpy(&NR_RRC_DCCH_DATA_IND(message_p).msg_integrity, msg_integrity, sizeof(*msg_integrity));
-    ue_id_t ue_id = ue->ue_id;
-    itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, message_p);
+    nr_pdcp_entity_t *rb = nr_pdcp_get_rb(ue, srb_id, true);
+    NR_RRC_DCCH_DATA_IND(message_p) =
+        (NRRrcDcchDataInd){.dcch_index = srb_id,
+                           .sdu_p = rrc_buffer_p,
+                           .sdu_size = size,
+                           .msg_integrity = *msg_integrity,
+                           .integrityResult = rb->check_integrity(rb, (const uint8_t *)buf, size, msg_integrity)};
+    itti_send_msg_to_task(TASK_RRC_NRUE, ue->ue_id, message_p);
+    MessageDef *Resp;
+    itti_receive_msg(TASK_PDCP_UE, &Resp);
+    if (Resp == NULL)
+      return;
+    RrcDcchDataResp *returned = &Resp->ittiMsg.nr_rrc_dcch_data_resp;
+    if (returned->doCyphering) {
+      // configure lower layers to apply SRB integrity protection and ciphering
+      for (i = 0; i < sizeofArray(ue->srb); i++) {
+        nr_pdcp_entity_t *rb = nr_pdcp_get_rb(ue, i, true);
+        if (rb)
+          rb->set_security(rb, returned->integrityProtAlgorithm, (char *)returned->kRRCint, 0, (char *)returned->kRRCenc);
+      }
+    }
+    if (returned->srbID) {
+      nr_pdcp_entity_t *rb = nr_pdcp_get_rb(ue, returned->srbID, true);
+      if (rb) {
+        char *ptr = (char *)returned->buffer;
+        for (int i = 0; i < sizeofArray(returned->sz) && returned->sz[i]; i++) {
+          int max_size = nr_max_pdcp_pdu_size(returned->sz[i]);
+          char pdu_buf[max_size];
+          int pdu_size = rb->process_sdu(rb, ptr, returned->sz[i], 0, pdu_buf, max_size);
+          deliver_pdu_srb_rlc(NULL, ue->ue_id, returned->srbID, pdu_buf, pdu_size, 0);
+          ptr += returned->sz[i];
+        }
+      }
+    }
+    if (returned->doCyphering) {
+      // configure lower layers to apply SRB integrity protection and ciphering
+      for (i = 0; i < sizeofArray(ue->srb); i++) {
+        nr_pdcp_entity_t *rb = nr_pdcp_get_rb(ue, i, true);
+        if (rb)
+          rb->set_security(rb,
+                           returned->integrityProtAlgorithm,
+                           (char *)returned->kRRCint,
+                           returned->cipheringAlgorithm,
+                           (char *)returned->kRRCenc);
+      }
+    }
+    itti_free(ITTI_MSG_ORIGIN_ID(Resp), Resp);
   }
 }
 
@@ -801,7 +842,8 @@ void add_srb(int is_gnb,
              int ciphering_algorithm,
              int integrity_algorithm,
              unsigned char *ciphering_key,
-             unsigned char *integrity_key)
+             unsigned char *integrity_key,
+             bool alreadyLocked)
 {
   nr_pdcp_entity_t *pdcp_srb;
   nr_pdcp_ue_t *ue;
@@ -811,7 +853,8 @@ void add_srb(int is_gnb,
   if (s->pdcp_Config != NULL && s->pdcp_Config->t_Reordering != NULL)
     t_Reordering = decode_t_reordering(*s->pdcp_Config->t_Reordering);
 
-  nr_pdcp_manager_lock(nr_pdcp_ue_manager);
+  if (!alreadyLocked)
+    nr_pdcp_manager_lock(nr_pdcp_ue_manager);
   ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, UEid);
   if (nr_pdcp_get_rb(ue, srb_id, true) != NULL) {
     LOG_E(PDCP, "warning SRB %d already exist for UE ID %ld, do nothing\n", srb_id, UEid);
@@ -837,7 +880,8 @@ void add_srb(int is_gnb,
 
     LOG_D(PDCP, "added srb %d to UE ID %ld\n", srb_id, UEid);
   }
-  nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
+  if (!alreadyLocked)
+    nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
 }
 
 void add_drb(int is_gnb,
@@ -846,7 +890,8 @@ void add_drb(int is_gnb,
              int ciphering_algorithm,
              int integrity_algorithm,
              unsigned char *ciphering_key,
-             unsigned char *integrity_key)
+             unsigned char *integrity_key,
+             bool alreadyLocked)
 {
   nr_pdcp_entity_t *pdcp_drb;
   nr_pdcp_ue_t *ue;
@@ -910,8 +955,8 @@ void add_drb(int is_gnb,
     exit(1);
   }
 
-
-  nr_pdcp_manager_lock(nr_pdcp_ue_manager);
+  if (!alreadyLocked)
+    nr_pdcp_manager_lock(nr_pdcp_ue_manager);
   ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, UEid);
   if (nr_pdcp_get_rb(ue, drb_id, false) != NULL) {
     LOG_W(PDCP, "warning DRB %d already exist for UE ID %ld, do nothing\n", drb_id, UEid);
@@ -940,7 +985,8 @@ void add_drb(int is_gnb,
                        mappedQFIs2Add,
                        mappedQFIs2AddCount);
   }
-  nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
+  if (!alreadyLocked)
+    nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
 }
 
 void nr_pdcp_add_srbs(eNB_flag_t enb_flag,
@@ -952,7 +998,14 @@ void nr_pdcp_add_srbs(eNB_flag_t enb_flag,
 {
   if (srb2add_list != NULL) {
     for (int i = 0; i < srb2add_list->list.count; i++) {
-      add_srb(enb_flag, UEid, srb2add_list->list.array[i], security_modeP & 0x0f, (security_modeP >> 4) & 0x0f, kRRCenc, kRRCint);
+      add_srb(enb_flag,
+              UEid,
+              srb2add_list->list.array[i],
+              security_modeP & 0x0f,
+              (security_modeP >> 4) & 0x0f,
+              kRRCenc,
+              kRRCint,
+              false);
     }
   } else
     LOG_W(PDCP, "nr_pdcp_add_srbs() with void list\n");
@@ -973,7 +1026,8 @@ void nr_pdcp_add_drbs(eNB_flag_t enb_flag,
               security_modeP & 0x0f,
               (security_modeP >> 4) & 0x0f,
               kUPenc,
-              kUPint);
+              kUPint,
+              false);
     }
   } else
     LOG_W(PDCP, "nr_pdcp_add_drbs() with void list\n");
@@ -1059,34 +1113,6 @@ void nr_pdcp_config_set_security(ue_id_t ue_id,
   nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
 }
 
-bool nr_pdcp_check_integrity_srb(ue_id_t ue_id,
-                                 int srb_id,
-                                 const uint8_t *msg,
-                                 int msg_size,
-                                 const nr_pdcp_integrity_data_t *msg_integrity)
-{
-  nr_pdcp_ue_t *ue;
-  nr_pdcp_entity_t *rb;
-
-  nr_pdcp_manager_lock(nr_pdcp_ue_manager);
-
-  ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id);
-
-  rb = nr_pdcp_get_rb(ue, srb_id, true);
-
-  if (rb == NULL) {
-    nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
-    LOG_E(PDCP, "no SRB found (ue_id %ld, rb_id %d)\n", ue_id, srb_id);
-    return false;
-  }
-
-  bool ret = rb->check_integrity(rb, msg, msg_size, msg_integrity);
-
-  nr_pdcp_manager_unlock(nr_pdcp_ue_manager);
-
-  return ret;
-}
-
 bool nr_pdcp_data_req_srb(ue_id_t ue_id,
                           const rb_id_t rb_id,
                           const mui_t muiP,
diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h
index 99f7fcdc816..119d5bec643 100644
--- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h
+++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h
@@ -59,7 +59,8 @@ void add_drb(int is_gnb,
              int ciphering_algorithm,
              int integrity_algorithm,
              unsigned char *ciphering_key,
-             unsigned char *integrity_key);
+             unsigned char *integrity_key,
+             bool alreadyLocked);
 
 void nr_pdcp_remove_UE(ue_id_t ue_id);
 void nr_pdcp_reestablishment(ue_id_t ue_id, int rb_id, bool srb_flag);
@@ -71,14 +72,14 @@ void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, NR_PDCP_Config_t *pdcp_c
 void nr_pdcp_release_srb(ue_id_t ue_id, int srb_id);
 void nr_pdcp_release_drb(ue_id_t ue_id, int drb_id);
 
-
 void add_srb(int is_gnb,
              ue_id_t UEid,
              struct NR_SRB_ToAddMod *s,
              int ciphering_algorithm,
              int integrity_algorithm,
              unsigned char *ciphering_key,
-             unsigned char *integrity_key);
+             unsigned char *integrity_key,
+             bool alreadyLocked);
 
 void nr_pdcp_config_set_security(ue_id_t ue_id,
                                  const rb_id_t rb_id,
@@ -87,12 +88,6 @@ void nr_pdcp_config_set_security(ue_id_t ue_id,
                                  uint8_t *const kRRCint_pP,
                                  uint8_t *const kUPenc_pP);
 
-bool nr_pdcp_check_integrity_srb(ue_id_t ue_id,
-                                 int srb_id,
-                                 const uint8_t *msg,
-                                 int msg_size,
-                                 const nr_pdcp_integrity_data_t *msg_integrity);
-
 bool cu_f1u_data_req(protocol_ctxt_t  *ctxt_pP,
                      const srb_flag_t srb_flagP,
                      const rb_id_t rb_id,
diff --git a/openair2/RRC/NR/nr_rrc_common.h b/openair2/RRC/NR/nr_rrc_common.h
index e1ff2e703e2..26837fb7aa5 100644
--- a/openair2/RRC/NR/nr_rrc_common.h
+++ b/openair2/RRC/NR/nr_rrc_common.h
@@ -24,7 +24,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdint.h> 
+#include <stdint.h>
 
 #define NR_RRC_HEADER_SIZE_MAX 64
 #define NR_RRC_BUFFER_SIZE_MAX 1024
diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c
index 980f793c0af..7686c4719c1 100644
--- a/openair2/RRC/NR_UE/rrc_UE.c
+++ b/openair2/RRC/NR_UE/rrc_UE.c
@@ -139,19 +139,37 @@ static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc,
 
 static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc,
                                                 NR_RadioBearerConfig_t *const radioBearerConfig);
-static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, const NR_RRCReestablishment_t *rrcReestablishment);
+static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc,
+                                                          const NR_RRCReestablishment_t *rrcReestablishment,
+                                                          RrcDcchDataResp *returned);
 static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_len);
 static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc,
                                                  int gNB_index,
                                                  NR_RRCReconfiguration_t *rrcReconfiguration);
 
-static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECapabilityEnquiry_t *UECapabilityEnquiry);
+static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc,
+                                                  NR_UECapabilityEnquiry_t *UECapabilityEnquiry,
+                                                  RrcDcchDataResp *returned);
 static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc,
                                               OCTET_STRING_t *masterCellGroup,
                                               long *fullConfig);
 
 static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers);
 
+static char *getRetBuf(RrcDcchDataResp *returned, int *maxSz, int **setSz)
+{
+  char *ptr = (char *)returned->buffer;
+  *maxSz = sizeof(returned->buffer);
+  int i;
+  for (i = 0; i < sizeofArray(returned->sz) && returned->sz[i]; i++) {
+    ptr += returned->sz[i];
+    *maxSz -= returned->sz[i];
+  }
+  *setSz = returned->sz + i;
+  AssertFatal(*maxSz > 0 && i < sizeofArray(returned->sz), "Buffers too small, change source code\n");
+  return ptr;
+}
+
 static NR_RB_status_t get_DRB_status(const NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id)
 {
   AssertFatal(drb_id > 0 && drb_id < 33, "Invalid DRB ID %ld\n", drb_id);
@@ -1009,7 +1027,9 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc,
                                                   int srb_id,
                                                   const uint8_t *msg,
                                                   int msg_size,
-                                                  const nr_pdcp_integrity_data_t *msg_integrity)
+                                                  const nr_pdcp_integrity_data_t *msg_integrity,
+                                                  const bool integrity_pass,
+                                                  RrcDcchDataResp *returned)
 {
   LOG_I(NR_RRC, "Receiving from SRB1 (DL-DCCH), Processing securityModeCommand\n");
 
@@ -1047,23 +1067,15 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc,
     ue_rrc->integrityProtAlgorithm = *securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm;
   }
 
-  uint8_t kRRCenc[NR_K_KEY_SIZE] = {0};
-  uint8_t  kUPenc[NR_K_KEY_SIZE] = {0};
-  uint8_t kRRCint[NR_K_KEY_SIZE] = {0};
-  nr_derive_key(UP_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kUPenc);
-  nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kRRCenc);
-  nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, kRRCint);
+  nr_derive_key(UP_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, returned->kUPenc);
+  nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, returned->kRRCenc);
+  nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, returned->kRRCint);
 
   log_dump(NR_RRC, ue_rrc->kgnb, 32, LOG_DUMP_CHAR, "deriving kRRCenc, kRRCint and kUPenc from KgNB=");
 
   /* for SecurityModeComplete, ciphering is not activated yet, only integrity */
-  uint8_t security_mode = ue_rrc->integrityProtAlgorithm << 4;
-  // configure lower layers to apply SRB integrity protection and ciphering
-  for (int i = 1; i < NR_NUM_SRB; i++) {
-    if (ue_rrc->Srb[i] == RB_ESTABLISHED)
-      nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, kRRCenc, kRRCint, kUPenc);
-  }
-
+  returned->integrityProtAlgorithm = ue_rrc->integrityProtAlgorithm;
+  returned->cipheringAlgorithm = ue_rrc->cipheringAlgorithm;
   NR_UL_DCCH_Message_t ul_dcch_msg = {0};
 
   ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1;
@@ -1071,7 +1083,6 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc,
 
   // the SecurityModeCommand message needs to pass the integrity protection check
   // for the UE to declare AS security to be activated
-  bool integrity_pass = nr_pdcp_check_integrity_srb(ue_rrc->ue_id, srb_id, msg, msg_size, msg_integrity);
   if (!integrity_pass) {
     /* - continue using the configuration used prior to the reception of the SecurityModeCommand message, i.e.
      *   neither apply integrity protection nor ciphering.
@@ -1084,68 +1095,40 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc,
     modeFailure->criticalExtensions.present = NR_SecurityModeFailure__criticalExtensions_PR_securityModeFailure;
     asn1cCalloc(modeFailure->criticalExtensions.choice.securityModeFailure, ext);
     ext->nonCriticalExtension = NULL;
+  } else {
+    /* integrity passed, send SecurityModeComplete */
+    c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete;
 
-    uint8_t buffer[200];
-    asn_enc_rval_t enc_rval =
-        uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, sizeof(buffer));
-    AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded);
-    if (LOG_DEBUGFLAG(DEBUG_ASN1))
-      xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg);
-    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_UL_DCCH_Message, &ul_dcch_msg);
-
-    /* disable both ciphering and integrity */
-    security_mode = 0;
-    for (int i = 1; i < NR_NUM_SRB; i++) {
-      if (ue_rrc->Srb[i] == RB_ESTABLISHED)
-        nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, NULL, NULL, NULL);
-    }
-
-    srb_id = 1; // SecurityModeFailure in SRB1
-    nr_pdcp_data_req_srb(ue_rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL);
-
-    return;
-  }
-
-  /* integrity passed, send SecurityModeComplete */
-  c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete;
-
-  asn1cCalloc(c1->choice.securityModeComplete, modeComplete);
-  modeComplete->rrc_TransactionIdentifier = securityModeCommand->rrc_TransactionIdentifier;
-  modeComplete->criticalExtensions.present = NR_SecurityModeComplete__criticalExtensions_PR_securityModeComplete;
-  asn1cCalloc(modeComplete->criticalExtensions.choice.securityModeComplete, ext);
-  ext->nonCriticalExtension = NULL;
-  LOG_I(NR_RRC,
-        "Receiving from SRB1 (DL-DCCH), encoding securityModeComplete, rrc_TransactionIdentifier: %ld\n",
-        securityModeCommand->rrc_TransactionIdentifier);
-  uint8_t buffer[200];
-  asn_enc_rval_t enc_rval =
-      uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, sizeof(buffer));
+    asn1cCalloc(c1->choice.securityModeComplete, modeComplete);
+    modeComplete->rrc_TransactionIdentifier = securityModeCommand->rrc_TransactionIdentifier;
+    modeComplete->criticalExtensions.present = NR_SecurityModeComplete__criticalExtensions_PR_securityModeComplete;
+    asn1cCalloc(modeComplete->criticalExtensions.choice.securityModeComplete, ext);
+    ext->nonCriticalExtension = NULL;
+    LOG_I(NR_RRC,
+          "encoding securityModeComplete, rrc_TransactionIdentifier: %ld\n",
+          securityModeCommand->rrc_TransactionIdentifier);
+    ue_rrc->as_security_activated = true;
+    /* after encoding SecurityModeComplete we activate both ciphering and integrity */
+    returned->doCyphering = true;
+    returned->doIntegrity = true;
+  }
+  int maxSz, *setSz;
+  char *buffer = getRetBuf(returned, &maxSz, &setSz);
+  asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, maxSz);
   AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded);
+  returned->srbID = 1; // SecurityMode answer in SRB1
+  *setSz = (enc_rval.encoded + 7) / 8;
 
-  if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
+  if (LOG_DEBUGFLAG(DEBUG_ASN1))
     xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg);
-  }
-  log_dump(NR_RRC, buffer, 16, LOG_DUMP_CHAR, "securityModeComplete payload: ");
-  LOG_D(NR_RRC, "securityModeComplete Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded + 7) / 8);
   ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_UL_DCCH_Message, &ul_dcch_msg);
 
-  for (int i = 0; i < (enc_rval.encoded + 7) / 8; i++) {
+  log_dump(NR_RRC, buffer, 16, LOG_DUMP_CHAR, "securityModeComplete payload: ");
+
+  for (int i = 0; i < *setSz; i++) {
     LOG_T(NR_RRC, "%02x.", buffer[i]);
   }
   LOG_T(NR_RRC, "\n");
-
-  ue_rrc->as_security_activated = true;
-  srb_id = 1; // SecurityModeComplete in SRB1
-  nr_pdcp_data_req_srb(ue_rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL);
-
-  /* after encoding SecurityModeComplete we activate both ciphering and integrity */
-  security_mode = ue_rrc->cipheringAlgorithm | (ue_rrc->integrityProtAlgorithm << 4);
-  // configure lower layers to apply SRB integrity protection and ciphering
-  for (int i = 1; i < NR_NUM_SRB; i++) {
-    if (ue_rrc->Srb[i] == RB_ESTABLISHED)
-      /* pass NULL to keep current keys */
-      nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, NULL, NULL, NULL);
-  }
 }
 
 static void handle_meas_reporting_remove(rrcPerNB_t *rrc, int id, NR_UE_Timers_Constants_t *timers)
@@ -1452,7 +1435,8 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc,
                 ue_rrc->cipheringAlgorithm,
                 ue_rrc->integrityProtAlgorithm,
                 kRRCenc,
-                kRRCint);
+                kRRCint,
+                true);
       }
       else {
         AssertFatal(srb->discardOnPDCP == NULL, "discardOnPDCP not yet implemented\n");
@@ -1510,7 +1494,8 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc,
                 ue_rrc->cipheringAlgorithm,
                 ue_rrc->integrityProtAlgorithm,
                 kUPenc,
-                kUPint);
+                kUPint,
+                true);
       }
     }
   } // drb_ToAddModList //
@@ -1519,23 +1504,28 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc,
   LOG_I(NR_RRC, "State = NR_RRC_CONNECTED\n");
 }
 
-static void nr_rrc_ue_generate_RRCReconfigurationComplete(NR_UE_RRC_INST_t *rrc, const int srb_id, const uint8_t Transaction_id)
+static void nr_rrc_ue_generate_RRCReconfigurationComplete(NR_UE_RRC_INST_t *rrc,
+                                                          const int srb_id,
+                                                          const uint8_t Transaction_id,
+                                                          RrcDcchDataResp *returned)
 {
-  uint8_t buffer[32];
-  int size = do_NR_RRCReconfigurationComplete(buffer, sizeof(buffer), Transaction_id);
-  LOG_I(NR_RRC, " Logical Channel UL-DCCH (SRB1), Generating RRCReconfigurationComplete (bytes %d)\n", size);
+  int maxSz, *setSz;
+  char *buffer = getRetBuf(returned, &maxSz, &setSz);
+  *setSz = do_NR_RRCReconfigurationComplete((uint8_t *)buffer, maxSz, Transaction_id);
+  LOG_I(NR_RRC, " Logical Channel UL-DCCH (SRB1), Generating RRCReconfigurationComplete (bytes %d)\n", *setSz);
   AssertFatal(srb_id == 1 || srb_id == 3, "Invalid SRB ID %d\n", srb_id);
   LOG_D(RLC,
         "PDCP_DATA_REQ/%d Bytes (RRCReconfigurationComplete) "
         "--->][PDCP][RB %02d]\n",
-        size,
+        *setSz,
         srb_id);
-  nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL);
+  returned->srbID = srb_id;
 }
 
 static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc,
                                                  const int gNB_index,
-                                                 const NR_RRCReestablishment_t *rrcReestablishment)
+                                                 const NR_RRCReestablishment_t *rrcReestablishment,
+                                                 RrcDcchDataResp *returned)
 {
   // implementign procedues as described in 38.331 section 5.3.7.5
   // stop timer T301
@@ -1580,17 +1570,21 @@ static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc,
   rrc->ra_trigger = RA_NOT_RUNNING;
 
   // submit the RRCReestablishmentComplete message to lower layers for transmission
-  nr_rrc_ue_generate_rrcReestablishmentComplete(rrc, rrcReestablishment);
+  nr_rrc_ue_generate_rrcReestablishmentComplete(rrc, rrcReestablishment, returned);
 }
 
-static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc,
-                                 const srb_id_t Srb_id,
-                                 const uint8_t *const Buffer,
-                                 size_t Buffer_size,
-                                 const uint8_t gNB_indexP,
-                                 const nr_pdcp_integrity_data_t *msg_integrity)
+static MessageDef *nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc,
+                                         const srb_id_t Srb_id,
+                                         const uint8_t *const Buffer,
+                                         size_t Buffer_size,
+                                         const uint8_t gNB_indexP,
+                                         const nr_pdcp_integrity_data_t *msg_integrity,
+                                         const bool integrity_pass)
 {
   NR_DL_DCCH_Message_t *dl_dcch_msg = NULL;
+  MessageDef *returnMsg = itti_alloc_new_message(TASK_PDCP_UE, 0, NR_RRC_DCCH_DATA_RESP);
+  RrcDcchDataResp *returned = &returnMsg->ittiMsg.nr_rrc_dcch_data_resp;
+  *returned = (RrcDcchDataResp){.doCyphering = false};
   if (Srb_id != 1 && Srb_id != 2) {
     LOG_E(NR_RRC, "Received message on DL-DCCH (SRB%ld), should not have ...\n", Srb_id);
   }
@@ -1601,7 +1595,7 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc,
   if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
     LOG_E(NR_RRC, "Failed to decode DL-DCCH (%zu bytes)\n", dec_rval.consumed);
     ASN_STRUCT_FREE(asn_DEF_NR_DL_DCCH_Message, dl_dcch_msg);
-    return -1;
+    return returnMsg;
   }
 
   if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
@@ -1618,7 +1612,10 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc,
 
         case NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration: {
           nr_rrc_ue_process_rrcReconfiguration(rrc, gNB_indexP, c1->choice.rrcReconfiguration);
-          nr_rrc_ue_generate_RRCReconfigurationComplete(rrc, Srb_id, c1->choice.rrcReconfiguration->rrc_TransactionIdentifier);
+          nr_rrc_ue_generate_RRCReconfigurationComplete(rrc,
+                                                        Srb_id,
+                                                        c1->choice.rrcReconfiguration->rrc_TransactionIdentifier,
+                                                        returned);
         } break;
 
         case NR_DL_DCCH_MessageType__c1_PR_rrcResume:
@@ -1634,12 +1631,12 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc,
 
         case NR_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry:
           LOG_I(NR_RRC, "Received Capability Enquiry (gNB %d)\n", gNB_indexP);
-          nr_rrc_ue_process_ueCapabilityEnquiry(rrc, c1->choice.ueCapabilityEnquiry);
+          nr_rrc_ue_process_ueCapabilityEnquiry(rrc, c1->choice.ueCapabilityEnquiry, returned);
           break;
 
         case NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment:
           LOG_I(NR_RRC, "Logical Channel DL-DCCH (SRB1), Received RRCReestablishment\n");
-          nr_rrc_ue_process_rrcReestablishment(rrc, gNB_indexP, c1->choice.rrcReestablishment);
+          nr_rrc_ue_process_rrcReestablishment(rrc, gNB_indexP, c1->choice.rrcReestablishment, returned);
           break;
 
         case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: {
@@ -1672,8 +1669,14 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc,
           break;
         case NR_DL_DCCH_MessageType__c1_PR_securityModeCommand:
           LOG_I(NR_RRC, "Received securityModeCommand (gNB %d)\n", gNB_indexP);
-          nr_rrc_ue_process_securityModeCommand(rrc, c1->choice.securityModeCommand,
-                                                Srb_id, Buffer, Buffer_size, msg_integrity);
+          nr_rrc_ue_process_securityModeCommand(rrc,
+                                                c1->choice.securityModeCommand,
+                                                Srb_id,
+                                                Buffer,
+                                                Buffer_size,
+                                                msg_integrity,
+                                                integrity_pass,
+                                                returned);
           break;
       }
     } break;
@@ -1682,7 +1685,7 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc,
   }
   //  release memory allocation
   SEQUENCE_free(&asn_DEF_NR_DL_DCCH_Message, (void *)dl_dcch_msg, 1);
-  return 0;
+  return returnMsg;
 }
 
 void nr_rrc_handle_ra_indication(NR_UE_RRC_INST_t *rrc, bool ra_succeeded)
@@ -1773,14 +1776,17 @@ void *rrc_nrue(void *notUsed)
     nr_rrc_ue_decode_ccch(rrc, ind);
   } break;
 
-  case NR_RRC_DCCH_DATA_IND:
-    nr_rrc_ue_decode_dcch(rrc,
-			  NR_RRC_DCCH_DATA_IND(msg_p).dcch_index,
-			  NR_RRC_DCCH_DATA_IND(msg_p).sdu_p,
-			  NR_RRC_DCCH_DATA_IND(msg_p).sdu_size,
-			  NR_RRC_DCCH_DATA_IND(msg_p).gNB_index,
-			  &NR_RRC_DCCH_DATA_IND(msg_p).msg_integrity);
-    break;
+  case NR_RRC_DCCH_DATA_IND: {
+    NRRrcDcchDataInd *tmp = &NR_RRC_DCCH_DATA_IND(msg_p);
+    MessageDef *msg = nr_rrc_ue_decode_dcch(rrc,
+                                            tmp->dcch_index,
+                                            tmp->sdu_p,
+                                            tmp->sdu_size,
+                                            tmp->gNB_index,
+                                            &tmp->msg_integrity,
+                                            tmp->integrityResult);
+    itti_send_msg_to_task(TASK_PDCP_UE, rrc->ue_id, msg);
+  } break;
 
   case NAS_KENB_REFRESH_REQ:
     memcpy(rrc->kgnb, NAS_KENB_REFRESH_REQ(msg_p).kenb, sizeof(rrc->kgnb));
@@ -1838,7 +1844,9 @@ void nr_rrc_ue_process_sidelink_radioResourceConfig(NR_SetupRelease_SL_ConfigDed
   }
 }
 
-static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECapabilityEnquiry_t *UECapabilityEnquiry)
+static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc,
+                                                  NR_UECapabilityEnquiry_t *UECapabilityEnquiry,
+                                                  RrcDcchDataResp *returned)
 {
   NR_UL_DCCH_Message_t ul_dcch_msg = {0};
   //
@@ -1890,17 +1898,19 @@ static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECa
   for (int i = 0; i < ueCapabilityEnquiry_ie->ue_CapabilityRAT_RequestList.list.count; i++) {
     if (ueCapabilityEnquiry_ie->ue_CapabilityRAT_RequestList.list.array[i]->rat_Type == NR_RAT_Type_nr) {
       asn1cSeqAdd(&UEcapList->list, &ue_CapabilityRAT_Container);
-      uint8_t buffer[500];
-      asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, 500);
+      int maxSz, *setSz;
+      char *buffer = getRetBuf(returned, &maxSz, &setSz);
+
+      asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, maxSz);
       AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n",
                    enc_rval.failed_type->name, enc_rval.encoded);
 
       if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
         xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg);
       }
-      LOG_I(NR_RRC, "UECapabilityInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
-      int srb_id = 1; // UECapabilityInformation on SRB1
-      nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL);
+      LOG_I(NR_RRC, "UECapabilityInformation Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded + 7) / 8);
+      returned->srbID = 1; // UECapabilityInformation on SRB1
+      *setSz = (enc_rval.encoded + 7) / 8;
     }
   }
 }
@@ -1945,14 +1955,15 @@ void nr_rrc_initiate_rrcReestablishment(NR_UE_RRC_INST_t *rrc,
 }
 
 static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc,
-                                                          const NR_RRCReestablishment_t *rrcReestablishment)
+                                                          const NR_RRCReestablishment_t *rrcReestablishment,
+                                                          RrcDcchDataResp *returned)
 {
-  uint8_t buffer[RRC_BUFFER_SIZE] = {0};
-  int size = do_RRCReestablishmentComplete(buffer, RRC_BUFFER_SIZE,
-                                           rrcReestablishment->rrc_TransactionIdentifier);
-  LOG_I(NR_RRC, "[RAPROC] Logical Channel UL-DCCH (SRB1), Generating RRCReestablishmentComplete (bytes %d)\n", size);
-  int srb_id = 1; // RRC re-establishment complete on SRB1
-  nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL);
+  int maxSz, *setSz;
+  char *buffer = getRetBuf(returned, &maxSz, &setSz);
+
+  *setSz = do_RRCReestablishmentComplete((uint8_t *)buffer, maxSz, rrcReestablishment->rrc_TransactionIdentifier);
+  LOG_I(NR_RRC, "[RAPROC] Logical Channel UL-DCCH (SRB1), Generating RRCReestablishmentComplete (bytes %d)\n", *setSz);
+  returned->srbID = 1; // RRC re-establishment complete on SRB1
 }
 
 void *recv_msgs_from_lte_ue(void *args_p)
-- 
GitLab