From 6b48fd6380424a00fe1bec170ee7639512bdda55 Mon Sep 17 00:00:00 2001
From: "Wilson W.K. Thong" <wilsonthong@astri.org>
Date: Mon, 2 May 2016 22:58:45 +0800
Subject: [PATCH] ** new procedure - refresh kENB from NAS -> AS **

added flow to refresh KeNB key in RRC on receiving S1AP-InitialContextSetup
added flow to configure PDCP security mode
enabled filling in the PDCP MAC code during and after RRC-SMC procedure

(cherry picked from commit 898cd5c45aedb27625d73352568211b4467c8dd9)
---
 openair2/COMMON/as_message.h                 | 10 +++
 openair2/COMMON/rrc_messages_def.h           |  3 +
 openair2/COMMON/rrc_messages_types.h         |  6 ++
 openair2/RRC/LITE/defs.h                     |  4 +
 openair2/RRC/LITE/rrc_UE.c                   | 94 ++++++++++++++++++++
 openair3/NAS/COMMON/API/NETWORK/l2_message.h | 10 +++
 openair3/NAS/UE/EMM/SecurityModeControl.c    |  6 +-
 openair3/NAS/UE/nas_itti_messaging.c         | 35 ++++++++
 openair3/NAS/UE/nas_itti_messaging.h         |  5 ++
 9 files changed, 172 insertions(+), 1 deletion(-)

diff --git a/openair2/COMMON/as_message.h b/openair2/COMMON/as_message.h
index 30810a325e..5f7f6f3fa9 100644
--- a/openair2/COMMON/as_message.h
+++ b/openair2/COMMON/as_message.h
@@ -220,6 +220,16 @@ typedef struct broadcast_info_ind_s {
 #define AS_HSDUPA           (1 << NET_ACCESS_HSDUPA)
 #define AS_EUTRAN           (1 << NET_ACCESS_EUTRAN)
 
+#if 1 // wilson 2016-05-02 add new message to update kenb in RRC after NAS SMC complete
+/*
+ * NAS->AS -K_eNB refresh request
+ * NAS request AS to refresh its KeNB key
+ */
+typedef struct kenb_refresh_req_s {
+  Byte_t kenb[32];
+} kenb_refresh_req_t;
+#endif
+
 /*
  * NAS->AS - Cell Information request
  * NAS request AS to search for a suitable cell belonging to the selected
diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h
index 27d3a6bdd4..d521eab0ff 100644
--- a/openair2/COMMON/rrc_messages_def.h
+++ b/openair2/COMMON/rrc_messages_def.h
@@ -64,6 +64,9 @@ MESSAGE_DEF(RRC_STATE_IND,              MESSAGE_PRIORITY_MED,       RrcStateInd,
 MESSAGE_DEF(RRC_CONFIGURATION_REQ,      MESSAGE_PRIORITY_MED,       RrcConfigurationReq,        rrc_configuration_req)
 
 // UE: NAS -> RRC messages
+#if 1 // wilson 2016-05-02 add new message to update kenb in RRC after NAS SMC complete
+MESSAGE_DEF(NAS_KENB_REFRESH_REQ,       MESSAGE_PRIORITY_MED,       NasKenbRefreshReq,          nas_kenb_refresh_req)
+#endif
 MESSAGE_DEF(NAS_CELL_SELECTION_REQ,     MESSAGE_PRIORITY_MED,       NasCellSelectionReq,        nas_cell_selection_req)
 MESSAGE_DEF(NAS_CONN_ESTABLI_REQ,       MESSAGE_PRIORITY_MED,       NasConnEstabliReq,          nas_conn_establi_req)
 MESSAGE_DEF(NAS_UPLINK_DATA_REQ,        MESSAGE_PRIORITY_MED,       NasUlDataReq,               nas_ul_data_req)
diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h
index ffe194265f..908510d94b 100644
--- a/openair2/COMMON/rrc_messages_types.h
+++ b/openair2/COMMON/rrc_messages_types.h
@@ -70,6 +70,9 @@ typedef UL_DCCH_Message_t       RrcUlDcchMessage;
 
 #define RRC_CONFIGURATION_REQ(mSGpTR)   (mSGpTR)->ittiMsg.rrc_configuration_req
 
+#if 1 // wilson 2016-05-02 add new message to update kenb in RRC after NAS SMC complete
+#define NAS_KENB_REFRESH_REQ(mSGpTR)    (mSGpTR)->ittiMsg.nas_kenb_refresh_req
+#endif
 #define NAS_CELL_SELECTION_REQ(mSGpTR)  (mSGpTR)->ittiMsg.nas_cell_selection_req
 #define NAS_CONN_ESTABLI_REQ(mSGpTR)    (mSGpTR)->ittiMsg.nas_conn_establi_req
 #define NAS_UPLINK_DATA_REQ(mSGpTR)     (mSGpTR)->ittiMsg.nas_ul_data_req
@@ -183,6 +186,9 @@ typedef struct RrcConfigurationReq_s {
 } RrcConfigurationReq;
 
 // UE: NAS -> RRC messages
+#if 1 // wilson 2016-05-02 add new message to update kenb in RRC after NAS SMC complete
+typedef kenb_refresh_req_t      NasKenbRefreshReq;
+#endif
 typedef cell_info_req_t         NasCellSelectionReq;
 typedef nas_establish_req_t     NasConnEstabliReq;
 typedef ul_info_transfer_req_t  NasUlDataReq;
diff --git a/openair2/RRC/LITE/defs.h b/openair2/RRC/LITE/defs.h
index e546b52f8e..e34c532990 100644
--- a/openair2/RRC/LITE/defs.h
+++ b/openair2/RRC/LITE/defs.h
@@ -182,7 +182,11 @@ typedef enum HO_STATE_e {
 #define PAYLOAD_SIZE_MAX 1024
 #define RRC_BUF_SIZE 255
 #define UNDEF_SECURITY_MODE 0xff
+#if 1 // wilson 2016-05-01 let RRC security mode command to return OK instead of failed
+#define NO_SECURITY_MODE 0x20
+#else
 #define NO_SECURITY_MODE 0x33
+#endif
 
 #define CBA_OFFSET        0xfff4
 // #define NUM_MAX_CBA_GROUP 4 // in the platform_constants
diff --git a/openair2/RRC/LITE/rrc_UE.c b/openair2/RRC/LITE/rrc_UE.c
index 01c1ee6ca9..51c7aa076d 100644
--- a/openair2/RRC/LITE/rrc_UE.c
+++ b/openair2/RRC/LITE/rrc_UE.c
@@ -39,6 +39,7 @@
 #define RRC_UE_C
 
 #include "assertions.h"
+#include "hashtable.h"
 #include "asn1_conversions.h"
 #include "defs.h"
 #include "PHY/TOOLS/dB_routines.h"
@@ -107,6 +108,15 @@ extern void *bigphys_malloc(int);
 
 extern int8_t dB_fixed2(uint32_t x,uint32_t y);
 
+extern void pdcp_config_set_security(
+  const protocol_ctxt_t* const  ctxt_pP,
+  pdcp_t         * const pdcp_pP,
+  const rb_id_t         rb_idP,
+  const uint16_t        lc_idP,
+  const uint8_t         security_modeP,
+  uint8_t        * const kRRCenc,
+  uint8_t        * const kRRCint,
+  uint8_t        * const  kUPenc);
 
 // internal prototypes
 
@@ -1392,6 +1402,64 @@ rrc_ue_process_securityModeCommand(
     ul_dcch_msg.message.choice.c1.present = UL_DCCH_MessageType__c1_PR_securityModeFailure;
   }
 
+
+#if 1 // wilson 2016-01-05 config PDCP security mode
+#if defined(ENABLE_SECURITY)
+  uint8_t *kRRCenc = NULL;
+  uint8_t *kUPenc = NULL;
+  uint8_t *kRRCint = NULL;
+  pdcp_t *pdcp_p = NULL;
+  hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
+  hashtable_rc_t h_rc;
+
+  key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti,
+      ctxt_pP->enb_flag, DCCH, SRB_FLAG_YES);
+  h_rc = hashtable_get(pdcp_coll_p, key, (void**) &pdcp_p);
+
+  if (h_rc == HASH_TABLE_OK) {
+    LOG_D(RRC, "PDCP_COLL_KEY_VALUE() returns valid key = %d\n", key);
+
+    LOG_D(RRC, "driving kRRCenc, kRRCint and kUPenc from KeNB="
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x"
+        "%02x%02x%02x%02x\n",
+        UE_rrc_inst[ctxt_pP->module_id].kenb[0],  UE_rrc_inst[ctxt_pP->module_id].kenb[1],  UE_rrc_inst[ctxt_pP->module_id].kenb[2],  UE_rrc_inst[ctxt_pP->module_id].kenb[3],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[4],  UE_rrc_inst[ctxt_pP->module_id].kenb[5],  UE_rrc_inst[ctxt_pP->module_id].kenb[6],  UE_rrc_inst[ctxt_pP->module_id].kenb[7],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[8],  UE_rrc_inst[ctxt_pP->module_id].kenb[9],  UE_rrc_inst[ctxt_pP->module_id].kenb[10], UE_rrc_inst[ctxt_pP->module_id].kenb[11],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[12], UE_rrc_inst[ctxt_pP->module_id].kenb[13], UE_rrc_inst[ctxt_pP->module_id].kenb[14], UE_rrc_inst[ctxt_pP->module_id].kenb[15],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[16], UE_rrc_inst[ctxt_pP->module_id].kenb[17], UE_rrc_inst[ctxt_pP->module_id].kenb[18], UE_rrc_inst[ctxt_pP->module_id].kenb[19],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[20], UE_rrc_inst[ctxt_pP->module_id].kenb[21], UE_rrc_inst[ctxt_pP->module_id].kenb[22], UE_rrc_inst[ctxt_pP->module_id].kenb[23],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[24], UE_rrc_inst[ctxt_pP->module_id].kenb[25], UE_rrc_inst[ctxt_pP->module_id].kenb[26], UE_rrc_inst[ctxt_pP->module_id].kenb[27],
+        UE_rrc_inst[ctxt_pP->module_id].kenb[28], UE_rrc_inst[ctxt_pP->module_id].kenb[29], UE_rrc_inst[ctxt_pP->module_id].kenb[30], UE_rrc_inst[ctxt_pP->module_id].kenb[31]);
+
+    derive_key_rrc_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
+        UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCenc);
+    derive_key_rrc_int(UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm,
+        UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCint);
+    derive_key_up_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
+        UE_rrc_inst[ctxt_pP->module_id].kenb, &kUPenc);
+
+    if (securityMode != 0xff) {
+      pdcp_config_set_security(ctxt_pP, pdcp_p, 0, 0,
+          UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm
+              | (UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm << 4),
+          kRRCenc, kRRCint, kUPenc);
+    } else {
+      LOG_W(RRC, "skipped pdcp_config_set_security() as securityMode == 0x%02x",
+          securityMode);
+    }
+  } else {
+    LOG_W(RRC, "Could not get PDCP instance where key=0x%\n", key);
+  }
+
+#endif //#if defined(ENABLE_SECURITY)
+#endif //#if 1 //wilson
+
   if (securityModeCommand->criticalExtensions.present == SecurityModeCommand__criticalExtensions_PR_c1) {
     if (securityModeCommand->criticalExtensions.choice.c1.present == SecurityModeCommand__criticalExtensions__c1_PR_securityModeCommand_r8) {
 
@@ -4063,6 +4131,32 @@ void *rrc_ue_task( void *args_p )
 
 # if defined(ENABLE_USE_MME)
 
+#if 1 // wilson 2016-05-02 add new message to update kenb in RRC after NAS SMC complete
+    case NAS_KENB_REFRESH_REQ:
+        memcpy((void*)UE_rrc_inst[ue_mod_id].kenb, (void*)NAS_KENB_REFRESH_REQ(msg_p).kenb, sizeof(UE_rrc_inst[ue_mod_id].kenb));
+
+        LOG_D(RRC, "[UE %d] Received %s: refreshed RRC::KeNB = "
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x"
+            "%02x%02x%02x%02x\n",
+            ue_mod_id, msg_name,
+            UE_rrc_inst[ue_mod_id].kenb[0],  UE_rrc_inst[ue_mod_id].kenb[1],  UE_rrc_inst[ue_mod_id].kenb[2],  UE_rrc_inst[ue_mod_id].kenb[3],
+            UE_rrc_inst[ue_mod_id].kenb[4],  UE_rrc_inst[ue_mod_id].kenb[5],  UE_rrc_inst[ue_mod_id].kenb[6],  UE_rrc_inst[ue_mod_id].kenb[7],
+            UE_rrc_inst[ue_mod_id].kenb[8],  UE_rrc_inst[ue_mod_id].kenb[9],  UE_rrc_inst[ue_mod_id].kenb[10], UE_rrc_inst[ue_mod_id].kenb[11],
+            UE_rrc_inst[ue_mod_id].kenb[12], UE_rrc_inst[ue_mod_id].kenb[13], UE_rrc_inst[ue_mod_id].kenb[14], UE_rrc_inst[ue_mod_id].kenb[15],
+            UE_rrc_inst[ue_mod_id].kenb[16], UE_rrc_inst[ue_mod_id].kenb[17], UE_rrc_inst[ue_mod_id].kenb[18], UE_rrc_inst[ue_mod_id].kenb[19],
+            UE_rrc_inst[ue_mod_id].kenb[20], UE_rrc_inst[ue_mod_id].kenb[21], UE_rrc_inst[ue_mod_id].kenb[22], UE_rrc_inst[ue_mod_id].kenb[23],
+            UE_rrc_inst[ue_mod_id].kenb[24], UE_rrc_inst[ue_mod_id].kenb[25], UE_rrc_inst[ue_mod_id].kenb[26], UE_rrc_inst[ue_mod_id].kenb[27],
+            UE_rrc_inst[ue_mod_id].kenb[28], UE_rrc_inst[ue_mod_id].kenb[29], UE_rrc_inst[ue_mod_id].kenb[30], UE_rrc_inst[ue_mod_id].kenb[31]);
+
+      break;
+#endif
+
       /* NAS messages */
     case NAS_CELL_SELECTION_REQ:
       ue_mod_id = 0; /* TODO force ue_mod_id to first UE, NAS UE not virtualized yet */
diff --git a/openair3/NAS/COMMON/API/NETWORK/l2_message.h b/openair3/NAS/COMMON/API/NETWORK/l2_message.h
index 02e5d87354..603f7c0d7d 100644
--- a/openair3/NAS/COMMON/API/NETWORK/l2_message.h
+++ b/openair3/NAS/COMMON/API/NETWORK/l2_message.h
@@ -116,6 +116,15 @@ Description Defines the messages supported by the Access Stratum sublayer
 #define AS_HSDUPA     (1 << NET_ACCESS_HSDUPA)
 #define AS_EUTRAN     (1 << NET_ACCESS_EUTRAN)
 
+/*
+ * NAS->AS -K_eNB refresh request
+ * NAS request AS to refresh its KeNB key
+ */
+typedef struct kenb_refresh_req_s {
+  Byte_t kenb[32];
+} kenb_refresh_req_t;
+
+#if 1 // wilson 2016-05-02 add new message to update kenb in RRC after NAS SMC complete
 /*
  * NAS->AS - Cell Information request
  * NAS request AS to search for a suitable cell belonging to the selected
@@ -125,6 +134,7 @@ typedef struct {
   plmn_t plmnID;  /* PLMN identifier         */
   Byte_t rat;   /* Bitmap - set of radio access technologies   */
 } cell_info_req_t;
+#endif
 
 /*
  * AS->NAS - Cell Information response
diff --git a/openair3/NAS/UE/EMM/SecurityModeControl.c b/openair3/NAS/UE/EMM/SecurityModeControl.c
index fd7e4c3991..fa500ad316 100755
--- a/openair3/NAS/UE/EMM/SecurityModeControl.c
+++ b/openair3/NAS/UE/EMM/SecurityModeControl.c
@@ -72,6 +72,8 @@ Description Defines the security mode control EMM procedure executed by the
 #include "secu_defs.h"
 #include "msc.h"
 
+#include "nas_itti_messaging.h"
+
 /****************************************************************************/
 /****************  E X T E R N A L    D E F I N I T I O N S  ****************/
 /****************************************************************************/
@@ -293,7 +295,9 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
 
       _emm_data.security->selected_algorithms.encryption = seea;
       _emm_data.security->selected_algorithms.integrity  = seia;
-
+#if 1 // wilson 2016-05-02 add new message to update kenb in RRC after NAS SMC complete
+      nas_itti_kenb_refresh_req(_security_data.kenb.value);
+#endif
     }
     /*
      * NAS security mode command not accepted by the UE
diff --git a/openair3/NAS/UE/nas_itti_messaging.c b/openair3/NAS/UE/nas_itti_messaging.c
index 7b8f630b89..ff16c83ebf 100755
--- a/openair3/NAS/UE/nas_itti_messaging.c
+++ b/openair3/NAS/UE/nas_itti_messaging.c
@@ -187,6 +187,41 @@ int nas_itti_protected_msg(const char *buffer, const nas_message_t *msg, const i
 
 extern unsigned char NB_eNB_INST;
 
+#if 1 // wilson 2016-05-02 add new message to update kenb in RRC after NAS SMC complete
+int nas_itti_kenb_refresh_req(const Byte_t kenb[32])
+{
+  MessageDef *message_p;
+
+  message_p = itti_alloc_new_message(TASK_NAS_UE, NAS_KENB_REFRESH_REQ);
+
+  memcpy(NAS_KENB_REFRESH_REQ(message_p).kenb, kenb, sizeof(NAS_KENB_REFRESH_REQ(message_p).kenb));
+
+  MSC_LOG_TX_MESSAGE(
+      MSC_NAS_UE,
+      MSC_RRC_UE,
+      NULL,0,
+      "0 NAS_KENB_REFRESH_REQ KeNB "
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x"
+      "%02x%02x%02x%02x",
+      kenb[0],  kenb[1],  kenb[2],  kenb[3],
+      kenb[4],  kenb[5],  kenb[6],  kenb[7],
+      kenb[8],  kenb[9],  kenb[10], kenb[11],
+      kenb[12], kenb[13], kenb[14], kenb[15],
+      kenb[16], kenb[17], kenb[18], kenb[19],
+      kenb[20], kenb[21], kenb[22], kenb[23],
+      kenb[24], kenb[25], kenb[26], kenb[27],
+      kenb[28], kenb[29], kenb[30], kenb[31]);
+
+  return itti_send_msg_to_task(TASK_RRC_UE, NB_eNB_INST + 0 /* TODO to be virtualized */, message_p);
+}
+#endif
+
 int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat)
 {
   MessageDef *message_p;
diff --git a/openair3/NAS/UE/nas_itti_messaging.h b/openair3/NAS/UE/nas_itti_messaging.h
index 9ea80f63c0..dc8d41a239 100755
--- a/openair3/NAS/UE/nas_itti_messaging.h
+++ b/openair3/NAS/UE/nas_itti_messaging.h
@@ -54,6 +54,11 @@ int nas_itti_protected_msg(
 
 
 # if defined(NAS_BUILT_IN_UE)
+
+#if 1 // wilson 2016-05-02 add new message to update kenb in RRC after NAS SMC complete
+int nas_itti_kenb_refresh_req(const Byte_t kenb[32]);
+#endif
+
 int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat);
 
 int nas_itti_nas_establish_req(as_cause_t cause, as_call_type_t type, as_stmsi_t s_tmsi, plmn_t plmnID, Byte_t *data_pP, uint32_t lengthP);
-- 
GitLab