From 6f5c0332a03537694e57250c4f80683e8be446e6 Mon Sep 17 00:00:00 2001
From: Lionel Gauthier <lionel.gauthier@eurecom.fr>
Date: Wed, 7 May 2014 14:47:50 +0000
Subject: [PATCH] For Sync only, still problem with NAS COUNT (TODO) and MAC-I
 (check on real PFT SIM)

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5311 818b1a75-f10b-46b9-bf7c-635c3b92a50f
---
 openair-cn/COMMON/mme_app_messages_types.h    |   3 +
 openair-cn/COMMON/nas_messages_types.h        |   2 +-
 openair-cn/MME_APP/mme_app_bearer.c           |  15 +-
 openair-cn/NAS/EURECOM-NAS/Makefile.inc       |   2 +-
 .../EURECOM-NAS/src/api/network/nas_message.c | 473 +++++++++----
 .../EURECOM-NAS/src/api/network/nas_message.h |  36 +-
 openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c   |  62 +-
 .../NAS/EURECOM-NAS/src/emm/Authentication.c  |   8 +-
 .../NAS/EURECOM-NAS/src/emm/LowerLayer.c      |  14 +
 .../EURECOM-NAS/src/emm/SecurityModeControl.c | 152 +++-
 openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h  |   4 +
 .../NAS/EURECOM-NAS/src/emm/msg/emm_cause.h   |   2 +-
 .../NAS/EURECOM-NAS/src/emm/sap/emm_as.c      | 436 +++++++++---
 .../NAS/EURECOM-NAS/src/emm/sap/emm_asDef.h   |   4 +
 .../NAS/EURECOM-NAS/src/emm/sap/emm_cn.c      |  13 +-
 .../NAS/EURECOM-NAS/src/emm/sap/emm_recv.c    |   8 +-
 .../NAS/EURECOM-NAS/src/emm/sap/emm_send.c    |   4 +-
 .../NAS/EURECOM-NAS/src/include/securityDef.h |   4 +-
 .../tst/as_simulator/nas_process.c            | 662 ++++++++++--------
 openair-cn/NAS/Makefile.am                    |   1 +
 openair-cn/NAS/Makefile.inc                   |   2 +-
 openair-cn/README                             |   4 +-
 openair-cn/S1AP/s1ap_mme_nas_procedures.c     |  16 +-
 openair-cn/SECU/nas_stream_eia2.c             |  51 +-
 openair-cn/SECU/secu_defs.h                   |   7 +
 25 files changed, 1366 insertions(+), 619 deletions(-)

diff --git a/openair-cn/COMMON/mme_app_messages_types.h b/openair-cn/COMMON/mme_app_messages_types.h
index ca5b205fb1..3b2f08d55e 100644
--- a/openair-cn/COMMON/mme_app_messages_types.h
+++ b/openair-cn/COMMON/mme_app_messages_types.h
@@ -26,6 +26,9 @@ typedef struct mme_app_connection_establishment_cnf_s {
     pre_emp_capability_t    bearer_qos_pre_emp_capability;
     ambr_t                  ambr;
 
+    /* Key eNB */
+    uint8_t                 keNB[32];
+
     nas_conn_est_cnf_t       nas_conn_est_cnf;
 } mme_app_connection_establishment_cnf_t;
 
diff --git a/openair-cn/COMMON/nas_messages_types.h b/openair-cn/COMMON/nas_messages_types.h
index ec2d751c8c..b66f9f16a9 100644
--- a/openair-cn/COMMON/nas_messages_types.h
+++ b/openair-cn/COMMON/nas_messages_types.h
@@ -170,7 +170,7 @@ typedef struct nas_pdn_connectivity_rsp_s {
     uint32_t                mme_ue_s1ap_id;
 
     /* Key eNB */
-    uint8_t                 keNB[32];
+    //uint8_t                 keNB[32];
 
     ambr_t                  ambr;
     ambr_t                  apn_ambr;
diff --git a/openair-cn/MME_APP/mme_app_bearer.c b/openair-cn/MME_APP/mme_app_bearer.c
index bf8ebb09da..de87e4c660 100644
--- a/openair-cn/MME_APP/mme_app_bearer.c
+++ b/openair-cn/MME_APP/mme_app_bearer.c
@@ -289,6 +289,7 @@ mme_app_handle_conn_est_cnf(
     mme_app_connection_establishment_cnf_t *establishment_cnf_p = NULL;
     bearer_context_t                       *current_bearer_p    = NULL;
     ebi_t                                   bearer_id           = 0;
+    uint8_t                                *keNB                = NULL;
 
     MME_APP_DEBUG("Received NAS_CONNECTION_ESTABLISHMENT_CNF from NAS\n");
 
@@ -332,6 +333,11 @@ mme_app_handle_conn_est_cnf(
     establishment_cnf_p->bearer_qos_pre_emp_capability     = current_bearer_p->pre_emp_capability;
     establishment_cnf_p->ambr                              = ue_context_p->used_ambr;
 
+    MME_APP_DEBUG("Derive keNB with UL NAS COUNT %x\n", nas_conn_est_cnf_pP->ul_nas_count);
+    derive_keNB(ue_context_p->vector_in_use->kasme, nas_conn_est_cnf_pP->ul_nas_count, &keNB); //156
+    memcpy(establishment_cnf_p->keNB, keNB, 32);
+    free(keNB);
+
     itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p);
 }
 
@@ -471,17 +477,18 @@ mme_app_handle_create_sess_resp(
     mme_app_dump_ue_contexts(&mme_app_desc.mme_ue_contexts);
 
     {
-        uint8_t *keNB = NULL;
+        //uint8_t *keNB = NULL;
 
         message_p = itti_alloc_new_message(TASK_MME_APP, NAS_PDN_CONNECTIVITY_RSP);
         memset((void*)&message_p->ittiMsg.nas_pdn_connectivity_rsp,
                 0,
                 sizeof(nas_pdn_connectivity_rsp_t));
 
-        derive_keNB(ue_context_p->vector_in_use->kasme, 156, &keNB);
-        memcpy(NAS_PDN_CONNECTIVITY_RSP(message_p).keNB, keNB, 32);
+        // moved to NAS_CONNECTION_ESTABLISHMENT_CONF, keNB not handled in NAS MME
+        //derive_keNB(ue_context_p->vector_in_use->kasme, 156, &keNB);
+        //memcpy(NAS_PDN_CONNECTIVITY_RSP(message_p).keNB, keNB, 32);
 
-        free(keNB);
+        //free(keNB);
 
         NAS_PDN_CONNECTIVITY_RSP(message_p).pti            = ue_context_p->pending_pdn_connectivity_req_pti;   // NAS internal ref
         NAS_PDN_CONNECTIVITY_RSP(message_p).ue_id          = ue_context_p->pending_pdn_connectivity_req_ue_id; // NAS internal ref
diff --git a/openair-cn/NAS/EURECOM-NAS/Makefile.inc b/openair-cn/NAS/EURECOM-NAS/Makefile.inc
index 1efed2d9da..314a445766 100644
--- a/openair-cn/NAS/EURECOM-NAS/Makefile.inc
+++ b/openair-cn/NAS/EURECOM-NAS/Makefile.inc
@@ -17,7 +17,7 @@ SRCDIR		= $(PROJDIR)/src
 INCDIR		= $(SRCDIR)/include
 UTILDIR		= $(SRCDIR)/util
 APIDIR		= $(SRCDIR)/api
-USERAPIDIR 	= $(APIDIR)/user
+USERAPIDIR  = $(APIDIR)/user
 NETAPIDIR  	= $(APIDIR)/network
 USIMAPIDIR 	= $(APIDIR)/usim
 MMEAPIDIR 	= $(APIDIR)/mme
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 5161a44dc0..2153eafe0d 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
@@ -31,6 +31,7 @@ Description	Defines the layer 3 messages supported by the NAS sublayer
 #if ((defined(EPC_BUILD) && defined(NAS_MME)) || (defined(ENABLE_NAS_UE_LOGGING) && defined(UE_BUILD) && defined(NAS_UE)))
 # include "nas_itti_messaging.h"
 #endif
+#include "secu_defs.h"
 
 /****************************************************************************/
 /****************  E X T E R N A L    D E F I N I T I O N S  ****************/
@@ -40,34 +41,55 @@ Description	Defines the layer 3 messages supported by the NAS sublayer
 /*******************  L O C A L    D E F I N I T I O N S  *******************/
 /****************************************************************************/
 
+
 /* Functions used to decode layer 3 NAS messages */
 static int _nas_message_header_decode(const char* buffer,
-			nas_message_security_header_t* header, int length);
+    nas_message_security_header_t* header, int length);
 static int _nas_message_plain_decode(const char* buffer,
-			const nas_message_security_header_t* header,
-			nas_message_plain_t* msg, int length);
+    const nas_message_security_header_t* header,
+    nas_message_plain_t* msg, int length);
 static int _nas_message_protected_decode(const char* buffer,
-			nas_message_security_header_t* header,
-			nas_message_plain_t* msg, int length);
+    nas_message_security_header_t* header,
+    nas_message_plain_t* msg, int length);
 
 /* Functions used to encode layer 3 NAS messages */
 static int _nas_message_header_encode(char* buffer,
-		const nas_message_security_header_t* header, int length);
+    const nas_message_security_header_t* header, int length);
 static int _nas_message_plain_encode(char* buffer,
-		const nas_message_security_header_t* header,
-		const nas_message_plain_t* msg, int length);
-static int _nas_message_protected_encode(char* buffer,
-		const nas_message_security_protected_t* msg, int length);
+    const nas_message_security_header_t* header,
+    const nas_message_plain_t* msg, int length);
+
+static int _nas_message_protected_encode(
+    char                                    *buffer,
+    const nas_message_security_protected_t  *msg,
+    int                                      length,
+    void                                    *security);
 
 /* Functions used to decrypt and encrypt layer 3 NAS messages */
-static int _nas_message_decrypt(char* dest, const char* src, UInt8_t type,
-				UInt32_t code, UInt8_t seq, int length);
-static int _nas_message_encrypt(char* dest, const char* src, UInt8_t type,
-				UInt32_t code, UInt8_t seq, int length);
+static int _nas_message_decrypt(
+    char* dest,
+    const char* src,
+    UInt8_t type,
+    UInt32_t code,
+    UInt8_t seq,
+    int length);
+
+static int
+_nas_message_encrypt(
+    char       *dest,
+    const char *src,
+    UInt8_t     type,
+    UInt32_t    code,
+    UInt8_t     seq,
+    int         length,
+    const emm_security_context_t * const emm_security_context);
 
 /* Functions used for integrity protection of layer 3 NAS messages */
-static UInt32_t _nas_message_get_mac(const char* buffer, UInt32_t count,
-				     int length);
+static UInt32_t _nas_message_get_mac(
+    const char                   * const buffer,
+    int                            const length,
+    int                            const direction,
+    const emm_security_context_t * const emm_security_context);
 
 /****************************************************************************/
 /******************  E X P O R T E D    F U N C T I O N S  ******************/
@@ -93,48 +115,60 @@ static UInt32_t _nas_message_get_mac(const char* buffer, UInt32_t count,
  **		 Others:	None                                       **
  **                                                                        **
  ***************************************************************************/
-int nas_message_encrypt(const char* inbuf, char* outbuf,
-			const nas_message_security_header_t* header, int length)
+int
+nas_message_encrypt(
+    const char                          *inbuf,
+    char                                *outbuf,
+    const nas_message_security_header_t *header,
+    int                                  length,
+    void                                *security)
 {
     LOG_FUNC_IN;
-
+    emm_security_context_t *emm_security_context   = (emm_security_context_t*)security;
     int bytes = length;
 
     /* Encode the header */
     int size = _nas_message_header_encode(outbuf, header, length);
 
     if (size < 0) {
-	LOG_FUNC_RETURN (TLV_ENCODE_BUFFER_TOO_SHORT);
+        LOG_FUNC_RETURN (TLV_ENCODE_BUFFER_TOO_SHORT);
     }
     else if (size > 1) {
-	/* Encrypt the plain NAS message */
-	bytes = _nas_message_encrypt(outbuf + size, inbuf,
-				     header->security_header_type,
-				     header->message_authentication_code,
-				     header->sequence_number,
-				     length - size);
-	/* Integrity protected the NAS message */
-	if (bytes > 0) {
-	    /* Compute offset of the sequence number field */
-	    int offset = size - sizeof(UInt8_t);
-	    /* Compute the NAS message authentication code */
-	    UInt32_t mac = _nas_message_get_mac(outbuf + offset,
-						0, // TODO !!! ul counter
-						length - offset);
-	    /* Set the message authentication code of the NAS message */
-	    *(UInt32_t*)(outbuf + sizeof(UInt8_t)) = mac;
-	}
+        /* Encrypt the plain NAS message */
+        bytes = _nas_message_encrypt(outbuf + size, inbuf,
+            header->security_header_type,
+            header->message_authentication_code,
+            header->sequence_number,
+            length - size,
+            emm_security_context);
+        /* Integrity protected the NAS message */
+        if (bytes > 0) {
+            /* Compute offset of the sequence number field */
+            int offset = size - sizeof(UInt8_t);
+            /* Compute the NAS message authentication code */
+            UInt32_t mac = _nas_message_get_mac(
+                outbuf + offset,
+                length - offset,
+#ifdef NAS_MME
+                SECU_DIRECTION_DOWNLINK,
+#else
+                SECU_DIRECTION_UPLINK,
+#endif
+                emm_security_context);
+            /* Set the message authentication code of the NAS message */
+            *(UInt32_t*)(outbuf + sizeof(UInt8_t)) = mac;
+        }
     }
     else {
-	/* The input buffer does not need to be encrypted */
-	memcpy(outbuf, inbuf, length);
+        /* The input buffer does not need to be encrypted */
+        memcpy(outbuf, inbuf, length);
     }
 
     if (bytes < 0) {
-	LOG_FUNC_RETURN (bytes);
+        LOG_FUNC_RETURN (bytes);
     }
     if (size > 1) {
- 	LOG_FUNC_RETURN (size + bytes);
+        LOG_FUNC_RETURN (size + bytes);
     }
     LOG_FUNC_RETURN (bytes);
 }
@@ -159,43 +193,54 @@ int nas_message_encrypt(const char* inbuf, char* outbuf,
  **		 Others:	None                                       **
  **                                                                        **
  ***************************************************************************/
-int nas_message_decrypt(const char* inbuf, char* outbuf,
-			nas_message_security_header_t* header, int length)
+int nas_message_decrypt(
+    const char                         *inbuf,
+    char                               *outbuf,
+    nas_message_security_header_t      *header,
+    int                                 length,
+    void                               *security)
 {
     LOG_FUNC_IN;
 
-    int bytes = length;
+    emm_security_context_t *emm_security_context   = (emm_security_context_t*)security;
+    int                     bytes                  = length;
 
     /* Decode the header */
     int size = _nas_message_header_decode(inbuf, header, length);
 
     if (size < 0) {
-	LOG_FUNC_RETURN (TLV_DECODE_BUFFER_TOO_SHORT);
+        LOG_FUNC_RETURN (TLV_DECODE_BUFFER_TOO_SHORT);
     }
     else if (size > 1) {
-	/* Compute offset of the sequence number field */
-	int offset = size - sizeof(UInt8_t);
-	/* Compute the NAS message authentication code */
-	UInt32_t mac = _nas_message_get_mac(inbuf + offset,
-					    0, // TODO !!! dl counter
-					    length - offset);
-	/* Check NAS message integrity */
-	if (mac != header->message_authentication_code) {
-	    LOG_FUNC_RETURN (TLV_DECODE_MAC_MISMATCH);
-	}
-
-	/* Decrypt the security protected NAS message */
-	header->protocol_discriminator =
-	    _nas_message_decrypt(outbuf, inbuf + size,
-				 header->security_header_type,
-				 header->message_authentication_code,
-				 header->sequence_number,
-				 length - size);
-	bytes = length - size;
+        /* Compute offset of the sequence number field */
+        int offset = size - sizeof(UInt8_t);
+        /* Compute the NAS message authentication code */
+        UInt32_t mac = _nas_message_get_mac(
+            inbuf + offset,
+            length - offset,
+#ifdef NAS_MME
+            SECU_DIRECTION_UPLINK,
+#else
+            SECU_DIRECTION_DOWNLINK,
+#endif
+            emm_security_context);
+        /* Check NAS message integrity */
+        if (mac != header->message_authentication_code) {
+            LOG_FUNC_RETURN (TLV_DECODE_MAC_MISMATCH);
+        }
+
+        /* Decrypt the security protected NAS message */
+        header->protocol_discriminator =
+            _nas_message_decrypt(outbuf, inbuf + size,
+                header->security_header_type,
+                header->message_authentication_code,
+                header->sequence_number,
+                length - size);
+        bytes = length - size;
     }
     else {
-	/* The input buffer contains a plain NAS message */
-	memcpy(outbuf, inbuf, length);
+        /* The input buffer contains a plain NAS message */
+        memcpy(outbuf, inbuf, length);
     }
 
     LOG_FUNC_RETURN (bytes);
@@ -219,10 +264,14 @@ int nas_message_decrypt(const char* inbuf, char* outbuf,
  **		 Others:	None                                       **
  **                                                                        **
  ***************************************************************************/
-int nas_message_decode(const char* const buffer, nas_message_t* msg, int length)
+int nas_message_decode(
+    const char* const   buffer,
+    nas_message_t      *msg,
+    int                 length,
+    void               *security)
 {
     LOG_FUNC_IN;
-
+    emm_security_context_t *emm_security_context   = (emm_security_context_t*)security;
     int bytes;
 #if ((defined(EPC_BUILD) && defined(NAS_MME)) || (defined(ENABLE_NAS_UE_LOGGING) && defined(UE_BUILD) && defined(NAS_UE)))
     int down_link;
@@ -244,9 +293,17 @@ int nas_message_decode(const char* const buffer, nas_message_t* msg, int length)
         /* Compute offset of the sequence number field */
         int offset = size - sizeof(UInt8_t);
         /* Compute the NAS message authentication code */
-        UInt32_t mac = _nas_message_get_mac(buffer + offset,
-                                            0, // TODO !!! dl counter
-                                            length - offset);
+        UInt32_t mac = _nas_message_get_mac(
+            buffer + offset,
+            length - offset,
+#ifdef NAS_MME
+            SECU_DIRECTION_UPLINK,
+#else
+            SECU_DIRECTION_DOWNLINK,
+#endif
+            emm_security_context
+            );
+
         /* Check NAS message integrity */
         if (mac != msg->header.message_authentication_code) {
             LOG_FUNC_RETURN (TLV_DECODE_MAC_MISMATCH);
@@ -292,10 +349,15 @@ int nas_message_decode(const char* const buffer, nas_message_t* msg, int length)
  **		 Others:	None                                       **
  **                                                                        **
  ***************************************************************************/
-int nas_message_encode(char* buffer, const nas_message_t* const msg, int length)
+int nas_message_encode(
+    char                *buffer,
+    const nas_message_t *const msg,
+    int                  length,
+    void                *security)
 {
     LOG_FUNC_IN;
 
+    emm_security_context_t *emm_security_context   = (emm_security_context_t*)security;
     int bytes;
 #if ((defined(EPC_BUILD) && defined(NAS_MME)) || (defined(ENABLE_NAS_UE_LOGGING) && defined(UE_BUILD) && defined(NAS_UE)))
     int down_link;
@@ -315,18 +377,47 @@ int nas_message_encode(char* buffer, const nas_message_t* const msg, int length)
     }
     else if (size > 1) {
         /* Encode security protected NAS message */
-        bytes = _nas_message_protected_encode(buffer + size, &msg->security_protected,
-                              length - size);
+        bytes = _nas_message_protected_encode(
+            buffer + size,
+            &msg->security_protected,
+            length - size,
+            emm_security_context);
         /* Integrity protect the NAS message */
         if (bytes > 0) {
             /* Compute offset of the sequence number field */
             int offset = size - sizeof(UInt8_t);
             /* Compute the NAS message authentication code */
-            UInt32_t mac = _nas_message_get_mac(buffer + offset,
-                            0, // TODO !!! ul counter
-                            length - offset);
+            UInt32_t mac = _nas_message_get_mac(
+                buffer + offset,
+                length - offset,
+#ifdef NAS_MME
+                SECU_DIRECTION_DOWNLINK,
+#else
+                SECU_DIRECTION_UPLINK,
+#endif
+                emm_security_context);
             /* Set the message authentication code of the NAS message */
             *(UInt32_t*)(buffer + sizeof(UInt8_t)) = mac;
+
+            if (emm_security_context) {
+#ifdef NAS_MME
+                emm_security_context->dl_count.seq_num += 1;
+                if ( ! emm_security_context->dl_count.seq_num) {
+                    emm_security_context->dl_count.overflow += 1;
+                    if ( ! emm_security_context->dl_count.overflow) {
+                        // TODO
+                    }
+                }
+#else
+                emm_security_context->ul_count.seq_num += 1;
+                if ( ! emm_security_context->ul_count.seq_num) {
+                    emm_security_context->ul_count.overflow += 1;
+                    if ( ! emm_security_context->ul_count.overflow) {
+                        // TODO
+                    }
+                }
+#endif
+            }
         }
 #if ((defined(EPC_BUILD) && defined(NAS_MME)) || (defined(ENABLE_NAS_UE_LOGGING) && defined(UE_BUILD) && defined(NAS_UE)))
         /* Log message header */
@@ -377,9 +468,11 @@ int nas_message_encode(char* buffer, const nas_message_t* const msg, int length)
  **		 Others:	None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _nas_message_header_decode(const char* buffer,
-                                      nas_message_security_header_t* header,
-                                      int length)
+static int
+_nas_message_header_decode(
+    const char                         *buffer,
+    nas_message_security_header_t      *header,
+    int                                 length)
 {
     LOG_FUNC_IN;
 
@@ -393,11 +486,11 @@ static int _nas_message_header_decode(const char* buffer,
         if (header->security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED)
         {
             if (length < NAS_MESSAGE_SECURITY_HEADER_SIZE) {
-            /* The buffer is not big enough to contain security header */
-            LOG_TRACE(WARNING, "NET-API   - The size of the header (%u) "
-                  "exceeds the buffer length (%u)",
-                  NAS_MESSAGE_SECURITY_HEADER_SIZE, length);
-            LOG_FUNC_RETURN (-1);
+                /* The buffer is not big enough to contain security header */
+                LOG_TRACE(WARNING, "NET-API   - The size of the header (%u) "
+                    "exceeds the buffer length (%u)",
+                    NAS_MESSAGE_SECURITY_HEADER_SIZE, length);
+                LOG_FUNC_RETURN (-1);
             }
             /* Decode the message authentication code */
             DECODE_U32(buffer+size, header->message_authentication_code, size);
@@ -428,26 +521,29 @@ static int _nas_message_header_decode(const char* buffer,
  **		 Others:	None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _nas_message_plain_decode(const char* buffer,
-				const nas_message_security_header_t* header,
-				nas_message_plain_t* msg, int length)
+static int
+_nas_message_plain_decode(
+    const char                          *buffer,
+    const nas_message_security_header_t *header,
+    nas_message_plain_t                 *msg,
+    int                                 length)
 {
     LOG_FUNC_IN;
 
     int bytes = TLV_DECODE_PROTOCOL_NOT_SUPPORTED;
 
     if (header->protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE) {
-	/* Decode EPS Mobility Management L3 message */
-	bytes = emm_msg_decode(&msg->emm, (uint8_t *)buffer, length);
+        /* Decode EPS Mobility Management L3 message */
+        bytes = emm_msg_decode(&msg->emm, (uint8_t *)buffer, length);
     }
     else if (header->protocol_discriminator == EPS_SESSION_MANAGEMENT_MESSAGE) {
-	/* Decode EPS Session Management L3 message */
-	bytes = esm_msg_decode(&msg->esm, (uint8_t *)buffer, length);
+        /* Decode EPS Session Management L3 message */
+        bytes = esm_msg_decode(&msg->esm, (uint8_t *)buffer, length);
     }
     else {
-	/* Discard L3 messages with not supported protocol discriminator */
-	LOG_TRACE(WARNING,"NET-API   - Protocol discriminator 0x%x is "
-		  "not supported", header->protocol_discriminator);
+        /* Discard L3 messages with not supported protocol discriminator */
+        LOG_TRACE(WARNING,"NET-API   - Protocol discriminator 0x%x is "
+            "not supported", header->protocol_discriminator);
     }
 
     LOG_FUNC_RETURN (bytes);
@@ -473,9 +569,11 @@ static int _nas_message_plain_decode(const char* buffer,
  **		 Others:	None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _nas_message_protected_decode(const char* buffer,
-				nas_message_security_header_t* header,
-				nas_message_plain_t* msg, int length)
+static int _nas_message_protected_decode(
+    const char                         *buffer,
+    nas_message_security_header_t      *header,
+    nas_message_plain_t                *msg,
+    int                                 length)
 {
     LOG_FUNC_IN;
 
@@ -484,15 +582,15 @@ static int _nas_message_protected_decode(const char* buffer,
     char* plain_msg = (char*)malloc(length);
     if (plain_msg)
     {
-	/* Decrypt the security protected NAS message */
-	header->protocol_discriminator =
-	    _nas_message_decrypt(plain_msg, buffer,
-				 header->security_header_type,
-				 header->message_authentication_code,
-				 header->sequence_number, length);
-	/* Decode the decrypted message as plain NAS message */
-	bytes = _nas_message_plain_decode(plain_msg, header, msg, length);
-	free(plain_msg);
+        /* Decrypt the security protected NAS message */
+        header->protocol_discriminator =
+            _nas_message_decrypt(plain_msg, buffer,
+                header->security_header_type,
+                header->message_authentication_code,
+                header->sequence_number, length);
+        /* Decode the decrypted message as plain NAS message */
+        bytes = _nas_message_plain_decode(plain_msg, header, msg, length);
+        free(plain_msg);
     }
 
     LOG_FUNC_RETURN (bytes);
@@ -523,8 +621,10 @@ static int _nas_message_protected_decode(const char* buffer,
  **		 Others:	None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _nas_message_header_encode(char* buffer,
-                                      const nas_message_security_header_t* header, int length)
+static int _nas_message_header_encode(
+    char                                       *buffer,
+    const nas_message_security_header_t        *header,
+    int                                         length)
 {
     LOG_FUNC_IN;
 
@@ -576,26 +676,28 @@ static int _nas_message_header_encode(char* buffer,
  **		 Others:	None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _nas_message_plain_encode(char* buffer,
-				const nas_message_security_header_t* header,
-				const nas_message_plain_t* msg, int length)
+static int _nas_message_plain_encode(
+    char                                *buffer,
+    const nas_message_security_header_t *header,
+    const nas_message_plain_t           *msg,
+    int                                  length)
 {
     LOG_FUNC_IN;
 
     int bytes = TLV_ENCODE_PROTOCOL_NOT_SUPPORTED;
 
     if (header->protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE) {
-	/* Encode EPS Mobility Management L3 message */
-	bytes = emm_msg_encode((EMM_msg*)(&msg->emm), (uint8_t*)buffer, length);
+        /* Encode EPS Mobility Management L3 message */
+        bytes = emm_msg_encode((EMM_msg*)(&msg->emm), (uint8_t*)buffer, length);
     }
     else if (header->protocol_discriminator == EPS_SESSION_MANAGEMENT_MESSAGE) {
-	/* Encode EPS Session Management L3 message */
-	bytes = esm_msg_encode((ESM_msg*)(&msg->esm), (uint8_t*)buffer, length);
+        /* Encode EPS Session Management L3 message */
+        bytes = esm_msg_encode((ESM_msg*)(&msg->esm), (uint8_t*)buffer, length);
     }
     else {
-	/* Discard L3 messages with not supported protocol discriminator */
-	LOG_TRACE(WARNING,"NET-API   - Protocol discriminator 0x%x is "
-		  "not supported", header->protocol_discriminator);
+        /* Discard L3 messages with not supported protocol discriminator */
+        LOG_TRACE(WARNING,"NET-API   - Protocol discriminator 0x%x is "
+            "not supported", header->protocol_discriminator);
     }
 
     LOG_FUNC_RETURN (bytes);
@@ -619,29 +721,36 @@ static int _nas_message_plain_encode(char* buffer,
  **		 Others:	None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _nas_message_protected_encode(char* buffer,
-			const nas_message_security_protected_t* msg, int length)
+static int _nas_message_protected_encode(
+    char                                       *buffer,
+    const nas_message_security_protected_t     *msg,
+    int                                         length,
+    void                                       *security)
 {
     LOG_FUNC_IN;
 
+    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);
     if (plain_msg) {
-	/* Encode the security protected NAS message as plain NAS message */
-	int size = _nas_message_plain_encode(plain_msg, &msg->header,
-					     &msg->plain, length);
-	if (size > 0) {
-	    //static uint8_t seq = 0;
-	    /* Encrypt the encoded plain NAS message */
-	    bytes = _nas_message_encrypt(buffer, plain_msg,
-					msg->header.security_header_type,
-					msg->header.message_authentication_code,
-					msg->header.sequence_number, size);
-					//seq, size);
-	    //seq ++;
-	}
-	free(plain_msg);
+        /* Encode the security protected NAS message as plain NAS message */
+        int size = _nas_message_plain_encode(plain_msg, &msg->header,
+            &msg->plain, length);
+        if (size > 0) {
+            //static uint8_t seq = 0;
+            /* Encrypt the encoded plain NAS message */
+            bytes = _nas_message_encrypt(buffer,
+                plain_msg,
+                msg->header.security_header_type,
+                msg->header.message_authentication_code,
+                msg->header.sequence_number,
+                size,
+                emm_security_context);
+            //seq, size);
+            //seq ++;
+        }
+        free(plain_msg);
     }
 
     LOG_FUNC_RETURN (bytes);
@@ -672,8 +781,13 @@ static int _nas_message_protected_encode(char* buffer,
  **		 Others:	None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _nas_message_decrypt(char* dest, const char* src, UInt8_t type,
-				UInt32_t code, UInt8_t seq, int length)
+static int _nas_message_decrypt(
+    char               *dest,
+    const char         *src,
+    UInt8_t             type,
+    UInt32_t            code,
+    UInt8_t             seq,
+    int                 length)
 {
     LOG_FUNC_IN;
 
@@ -710,8 +824,14 @@ static int _nas_message_decrypt(char* dest, const char* src, UInt8_t type,
  **		 Others:	None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _nas_message_encrypt(char* dest, const char* src, UInt8_t type,
-				UInt32_t code, UInt8_t seq, int length)
+static int _nas_message_encrypt(
+    char        *dest,
+    const char  *src,
+    UInt8_t     type,
+    UInt32_t    code,
+    UInt8_t     seq,
+    int         length,
+    const emm_security_context_t * const emm_security_context)
 {
     LOG_FUNC_IN;
 
@@ -748,17 +868,80 @@ static int _nas_message_encrypt(char* dest, const char* src, UInt8_t type,
  **		 Others:	None                                       **
  **                                                                        **
  ***************************************************************************/
-static UInt32_t _nas_message_get_mac(const char* buffer, UInt32_t count,
-				     int length)
+static UInt32_t _nas_message_get_mac(
+    const char                   * const buffer,
+    int                            const length,
+    int                            const direction,
+    const emm_security_context_t * const emm_security_context)
 {
+
     LOG_FUNC_IN;
-    /* TODO: run integrity protection algorithm */
-    /* TODO: Return the message authentication code */
+
+    if (!emm_security_context) {
+        LOG_TRACE(DEBUG,
+            "No security context set for integrity protection algorithm");
 #if defined(EPC_BUILD) || defined(UE_BUILD)
-    LOG_FUNC_RETURN (0);
+        LOG_FUNC_RETURN (0);
+#else
+        LOG_FUNC_RETURN (0xabababab);
+#endif
+    }
+
+    switch (emm_security_context->selected_algorithms.integrity) {
+
+        case NAS_SECURITY_ALGORITHMS_EIA1:
+            AssertFatal(0 ,
+                "EIA1_128_ALG_ID not implemented");
+            break;
+
+        case NAS_SECURITY_ALGORITHMS_EIA2: {
+                UInt8_t             mac[4];
+                nas_stream_cipher_t stream_cipher;
+                UInt32_t            count;
+                UInt32_t           *mac32;
+
+                if (direction == SECU_DIRECTION_UPLINK) {
+                    count = 0x00000000 ||
+                        ((emm_security_context->ul_count.overflow && 0x0000FFFF) << 8) ||
+                        (emm_security_context->ul_count.seq_num & 0x000000FF);
+                } else {
+                    count = 0x00000000 ||
+                        ((emm_security_context->dl_count.overflow && 0x0000FFFF) << 8) ||
+                        (emm_security_context->dl_count.seq_num & 0x000000FF);
+                }
+                stream_cipher.key        = emm_security_context->knas_int.value;
+                stream_cipher.key_length = AUTH_KNAS_INT_SIZE;
+                stream_cipher.count      = count;
+                stream_cipher.bearer     = 0x00; //33.401 section 8.1.1
+                stream_cipher.direction  = direction;
+                stream_cipher.message    = buffer;
+                    /* length in bits */
+                stream_cipher.blength    = length << 3;
+
+                nas_stream_encrypt_eia2(
+                    &stream_cipher,
+                    mac);
+                LOG_TRACE(DEBUG,
+                    "NAS_SECURITY_ALGORITHMS_EIA2 returned MAC %x.%x.%x.%x for length %d direction %d, count %d",
+                    mac[0], mac[1], mac[2],mac[3], length, direction, count);
+                mac32 = (UInt32_t*)&mac;
+                LOG_FUNC_RETURN (*mac32);
+            }break;
+
+        case NAS_SECURITY_ALGORITHMS_EIA0:
+#if defined(EPC_BUILD) || defined(UE_BUILD)
+            LOG_FUNC_RETURN (0);
 #else
-    LOG_FUNC_RETURN (0xabababab);
+            LOG_FUNC_RETURN (0xabababab);
 #endif
+            break;
+
+        default:
+          AssertFatal(0 ,
+              "Unknown integrity protection algorithm %d",
+              emm_security_context->selected_algorithms.integrity);
+    }
+    LOG_FUNC_RETURN (0);
 }
 
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/api/network/nas_message.h b/openair-cn/NAS/EURECOM-NAS/src/api/network/nas_message.h
index ab78123b24..c90b4c00dd 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/api/network/nas_message.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/api/network/nas_message.h
@@ -23,6 +23,9 @@ Description Defines the layer 3 messages supported by the NAS sublayer
 
 #include "commonDef.h"
 #include "emm_msg.h"
+#if defined(EPC_BUILD)
+#include "emmData.h"
+#endif
 #include "esm_msg.h"
 
 /****************************************************************************/
@@ -78,14 +81,29 @@ typedef union {
 /******************  E X P O R T E D    F U N C T I O N S  ******************/
 /****************************************************************************/
 
-int nas_message_encrypt(const char *inbuf, char *outbuf,
-                        const nas_message_security_header_t *header, int length);
-
-int nas_message_decrypt(const char *inbuf, char *outbuf,
-                        nas_message_security_header_t *header, int length);
-
-int nas_message_decode(const char * const buffer, nas_message_t *msg, int length);
-
-int nas_message_encode(char *buffer, const nas_message_t * const msg, int length);
+int nas_message_encrypt(
+    const char                          *inbuf,
+    char                                *outbuf,
+    const nas_message_security_header_t *header,
+    int                                  length,
+    void                                *security);
+
+int nas_message_decrypt(const char *inbuf,
+    char                           *outbuf,
+    nas_message_security_header_t  *header,
+    int                             length,
+    void                           *security);
+
+int nas_message_decode(
+    const char * const  buffer,
+    nas_message_t      *msg,
+    int                 length,
+    void               *security);
+
+int nas_message_encode(
+    char                       *buffer,
+    const nas_message_t * const msg,
+    int                         length,
+    void                       *security);
 
 #endif /* __NAS_MESSAGE_H__*/
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c b/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c
index 6bfb52521a..d308432b2d 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c
@@ -45,6 +45,8 @@ Description Defines the attach related EMM procedure executed by the
 #include "esm_sap.h"
 #include "emm_cause.h"
 
+#include "NasSecurityAlgorithms.h"
+
 #ifdef NAS_MME
 #include "mme_api.h"
 # if defined(EPC_BUILD)
@@ -1133,6 +1135,17 @@ int emm_proc_attach_request(unsigned int ueid, emm_proc_attach_type_t type,
 #if defined(EPC_BUILD)
         emm_data_context_add(&_emm_data, *(emm_ctx));
 #endif
+
+#warning "TRICK TO SET TAC, BUT LOOK AT SPEC"
+        if (tai){
+            LOG_TRACE(WARNING,
+                "EMM-PROC  - Set tac %u in context %u ",
+                tai->tac);
+            (*emm_ctx)->tac = tai->tac;
+        } else {
+            LOG_TRACE(WARNING,
+                "EMM-PROC  - Could not set tac in context, cause tai is NULL ");
+        }
     }
 
     /* Update the EMM context with the current attach procedure parameters */
@@ -2040,6 +2053,8 @@ static int _emm_attach_security(void *args)
     if (emm_ctx->security) {
         memset(emm_ctx->security, 0, sizeof(emm_security_context_t));
         emm_ctx->security->type = EMM_KSI_NOT_AVAILABLE;
+        emm_ctx->security->selected_algorithms.encryption = NAS_SECURITY_ALGORITHMS_EEA0;
+        emm_ctx->security->selected_algorithms.integrity  = NAS_SECURITY_ALGORITHMS_EIA0;
     } else {
         LOG_TRACE(WARNING, "EMM-PROC  - Failed to create security context");
         emm_ctx->emm_cause = EMM_CAUSE_ILLEGAL_UE;
@@ -2309,62 +2324,63 @@ static int _emm_attach_have_changed(const emm_data_context_t *ctx,
                                     GUTI_t *guti, imsi_t *imsi, imei_t *imei,
                                     int eea, int eia)
 {
+    LOG_FUNC_IN;
     /* Emergency bearer services indicator */
     if ( (type == EMM_ATTACH_TYPE_EMERGENCY) != ctx->is_emergency) {
-        return (TRUE);
+        LOG_FUNC_RETURN (TRUE);
     }
     /* Security key set identifier */
     if (ksi != ctx->ksi) {
-        return (TRUE);
+        LOG_FUNC_RETURN (TRUE);
     }
     /* Supported EPS encryption algorithms */
     if (eea != ctx->eea) {
-        return (TRUE);
+        LOG_FUNC_RETURN (TRUE);
     }
     /* Supported EPS integrity algorithms */
     if (eia != ctx->eia) {
-        return (TRUE);
+        LOG_FUNC_RETURN (TRUE);
     }
     /* The GUTI if provided by the UE */
     if ( (guti) && (ctx->guti == NULL) ) {
-        return (TRUE);
+        LOG_FUNC_RETURN (TRUE);
     }
     if ( (guti == NULL) && (ctx->guti) ) {
-        return (TRUE);
+        LOG_FUNC_RETURN (TRUE);
     }
     if ( (guti) && (ctx->guti) ) {
         if (guti->m_tmsi != ctx->guti->m_tmsi) {
-            return (TRUE);
+            LOG_FUNC_RETURN (TRUE);
         }
         if ( memcmp(&guti->gummei, &ctx->guti->gummei, sizeof(gummei_t)) != 0 ) {
-            return (TRUE);
+            LOG_FUNC_RETURN (TRUE);
         }
     }
     /* The IMSI if provided by the UE */
     if ( (imsi) && (ctx->imsi == NULL) ) {
-        return (TRUE);
+        LOG_FUNC_RETURN (TRUE);
     }
     if ( (imsi == NULL) && (ctx->imsi) ) {
-        return (TRUE);
+        LOG_FUNC_RETURN (TRUE);
     }
     if ( (imsi) && (ctx->imsi) ) {
         if ( memcmp(imsi, ctx->imsi, sizeof(imsi_t)) != 0 ) {
-            return (TRUE);
+            LOG_FUNC_RETURN (TRUE);
         }
     }
     /* The IMEI if provided by the UE */
     if ( (imei) && (ctx->imei == NULL) ) {
-        return (TRUE);
+        LOG_FUNC_RETURN (TRUE);
     }
     if ( (imei == NULL) && (ctx->imei) ) {
-        return (TRUE);
+        LOG_FUNC_RETURN (TRUE);
     }
     if ( (imei) && (ctx->imei) ) {
         if ( memcmp(imei, ctx->imei, sizeof(imei_t)) != 0 ) {
-            return (TRUE);
+            LOG_FUNC_RETURN (TRUE);
         }
     }
-    return (FALSE);
+    LOG_FUNC_RETURN (FALSE);
 }
 
 /****************************************************************************
@@ -2396,6 +2412,7 @@ static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid,
                               GUTI_t *guti, imsi_t *imsi, imei_t *imei,
                               int eea, int eia, const OctetString *esm_msg)
 {
+    LOG_FUNC_IN;
     /* UE identifier */
     ctx->ueid = ueid;
     /* Emergency bearer services indicator */
@@ -2414,7 +2431,7 @@ static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid,
         if (ctx->guti != NULL) {
             memcpy(ctx->guti, guti, sizeof(GUTI_t));
         } else {
-            return (RETURNerror);
+            LOG_FUNC_RETURN (RETURNerror);
         }
     } else {
         if (ctx->guti == NULL) {
@@ -2422,6 +2439,7 @@ static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid,
         }
         if (ctx->guti != NULL) {
             /* TODO: FIXME */
+            LOG_TRACE(WARNING, "EMM-PROC  - Assign hardcoded PLMN 208.92 and tac 0001 to emm_data_context");
             ctx->guti->gummei.plmn.MCCdigit1 = 2;
             ctx->guti->gummei.plmn.MCCdigit2 = 0;
             ctx->guti->gummei.plmn.MCCdigit3 = 8;
@@ -2433,8 +2451,10 @@ static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid,
             ctx->guti->gummei.MMEgid  = 0;
 
             ctx->guti->m_tmsi = (uint32_t) ctx;
+
+            ctx->tac          = 1;
         } else {
-            return (RETURNerror);
+            LOG_FUNC_RETURN (RETURNerror);
         }
     }
     /* The IMSI if provided by the UE */
@@ -2445,7 +2465,7 @@ static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid,
         if (ctx->imsi != NULL) {
             memcpy(ctx->imsi, imsi, sizeof(imsi_t));
         } else {
-            return (RETURNerror);
+            LOG_FUNC_RETURN (RETURNerror);
         }
     }
     /* The IMEI if provided by the UE */
@@ -2456,7 +2476,7 @@ static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid,
         if (ctx->imei != NULL) {
             memcpy(ctx->imei, imei, sizeof(imei_t));
         } else {
-            return (RETURNerror);
+            LOG_FUNC_RETURN (RETURNerror);
         }
     }
     /* The ESM message contained within the attach request */
@@ -2468,14 +2488,14 @@ static int _emm_attach_update(emm_data_context_t *ctx, unsigned int ueid,
             strncpy((char *)ctx->esm_msg.value,
                     (char *)esm_msg->value, esm_msg->length);
         } else {
-            return (RETURNerror);
+            LOG_FUNC_RETURN (RETURNerror);
         }
     }
     ctx->esm_msg.length = esm_msg->length;
     /* Attachment indicator */
     ctx->is_attached = FALSE;
 
-    return (RETURNok);
+    LOG_FUNC_RETURN (RETURNok);
 }
 
 #endif // NAS_MME
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/Authentication.c b/openair-cn/NAS/EURECOM-NAS/src/emm/Authentication.c
index 0346101068..acf4fa88a9 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/Authentication.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/Authentication.c
@@ -670,6 +670,8 @@ int emm_proc_authentication_complete(unsigned int ueid, int emm_cause,
             /* RES does not match the XRES parameter */
             LOG_TRACE(WARNING, "EMM-PROC  - Failed to authentify the UE");
             emm_cause = EMM_CAUSE_ILLEGAL_UE;
+        } else {
+            LOG_TRACE(DEBUG, "EMM-PROC  - Success to authentify the UE  RESP XRES == XRES UE CONTEXT");
         }
     }
 
@@ -1151,10 +1153,10 @@ static int _authentication_kasme(const OctetString *autn,
     /* Compute the KDF input parameter
      * S = FC(0x10) || SNid || 0x00 0x03 || SQN ⊕ AK || 0x00 0x06
      */
-    UInt8_t input[kasme->length];
+    UInt8_t  input[kasme->length];
     UInt16_t length;
-    int offset = 0;
-    int size_of_length = sizeof(length);
+    int      offset         = 0;
+    int      size_of_length = sizeof(length);
     input[offset] = 0x10;
     offset += 1;
     length = AUTH_SNID_SIZE;
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/LowerLayer.c b/openair-cn/NAS/EURECOM-NAS/src/emm/LowerLayer.c
index 49042cea1c..50a7a99458 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/LowerLayer.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/LowerLayer.c
@@ -30,6 +30,7 @@ Description Defines EMM procedures executed by the Non-Access Stratum
 
 #include "emm_sap.h"
 #include "esm_sap.h"
+#include "nas_log.h"
 
 #include <string.h> // memset
 
@@ -457,6 +458,14 @@ void emm_as_set_security_data(emm_as_security_data_t *data, const void *args,
          * into use, UE and MME shall cipher and integrity protect all
          * NAS signalling messages with the selected NAS ciphering and
          * NAS integrity algorithms */
+        LOG_TRACE(WARNING,
+            "EPS security context exists is new %u KSI %u SQN %u count %u knas_int %s",
+            is_new,
+            context->eksi,
+            context->ul_count.seq_num,
+            *(UInt32_t *)(&context->ul_count),
+            context->knas_int.value
+            );
         data->is_new = is_new;
         data->ksi = context->eksi;
         data->sqn = context->ul_count.seq_num;
@@ -473,9 +482,14 @@ void emm_as_set_security_data(emm_as_security_data_t *data, const void *args,
             /* 3GPP TS 24.301, section 5.4.3.2
              * The MME shall send the SECURITY MODE COMMAND message integrity
              * protected and unciphered */
+            LOG_TRACE(WARNING,
+                "EPS security context exists knas_enc %s",
+                context->knas_enc.value
+                );
             data->k_enc = &context->knas_enc;
         }
     } else {
+        LOG_TRACE(WARNING, "EMM_AS_NO_KEY_AVAILABLE");
         /* No valid EPS security context exists */
         data->ksi = EMM_AS_NO_KEY_AVAILABLE;
     }
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/SecurityModeControl.c b/openair-cn/NAS/EURECOM-NAS/src/emm/SecurityModeControl.c
index 8027d81ece..1492f27afa 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/SecurityModeControl.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/SecurityModeControl.c
@@ -46,6 +46,7 @@ Description Defines the security mode control EMM procedure executed by the
 #if defined(ENABLE_ITTI)
 # include "assertions.h"
 #endif
+#include "secu_defs.h"
 
 /****************************************************************************/
 /****************  E X T E R N A L    D E F I N I T I O N S  ****************/
@@ -98,20 +99,26 @@ static void *_security_t3460_handler(void *);
  * retransmission timer counter is exceed
  */
 static int _security_abort(void *);
-
+static int _security_select_algorithms(
+    const int   ue_eiaP,
+    const int   ue_eeaP,
+    int * const mme_eiaP,
+    int * const mme_eeaP);
 /*
  * 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 ksi;                /* NAS key set identifier               */
+    int eea;                /* Replayed EPS encryption algorithms   */
+    int eia;                /* Replayed EPS integrity algorithms    */
+    int selected_eea;       /* Replayed EPS encryption algorithms   */
+    int selected_eia;       /* Replayed EPS integrity algorithms    */
     int notify_failure;     /* Indicates whether the security mode control
-                 * procedure failure shall be notified to the
-                 * ongoing EMM procedure        */
+                             * procedure failure shall be notified to the
+                             * ongoing EMM procedure        */
 } security_data_t;
 
 static int _security_request(security_data_t *data, int is_new);
@@ -332,6 +339,8 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
  * --------------------------------------------------------------------------
  */
 #ifdef NAS_MME
+
+
 /****************************************************************************
  **                                                                        **
  ** Name:    emm_proc_security_mode_control()                          **
@@ -372,14 +381,16 @@ int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
 {
     int rc = RETURNerror;
     int security_context_is_new = FALSE;
-
+    int mme_eea                 = NAS_SECURITY_ALGORITHMS_EEA0;
+    int mme_eia                 = NAS_SECURITY_ALGORITHMS_EIA0;
     /* Get the UE context */
     emm_data_context_t *emm_ctx = NULL;
 
     LOG_FUNC_IN;
 
     LOG_TRACE(INFO, "EMM-PROC  - Initiate security mode control procedure "
-              "KSI = %d", ksi);
+              "KSI = %d EEA = %d EIA = %d",
+              ksi, eea, eia);
 
 #if defined(EPC_BUILD)
     if (ueid > 0) {
@@ -402,6 +413,52 @@ int emm_proc_security_mode_control(unsigned int ueid, int ksi, int eea, int eia,
             emm_ctx->security->dl_count.seq_num = 0;
 
             /* TODO !!! Compute Kasme, and NAS cyphering and integrity keys */
+            // LG: Kasme should have been received from authentication
+            //     information request (S6A)
+            // Kasme is located in emm_ctx->vector.kasme
+
+            rc = _security_select_algorithms(
+                eia,
+                eea,
+                &mme_eia,
+                &mme_eea);
+
+            emm_ctx->security->selected_algorithms.encryption = mme_eea;
+            emm_ctx->security->selected_algorithms.integrity  = mme_eia;
+
+            if (rc == RETURNerror) {
+                LOG_TRACE(WARNING,
+                    "EMM-PROC  - Failed to select security algorithms");
+                LOG_FUNC_RETURN (RETURNerror);
+            }
+
+            if ( ! emm_ctx->security->knas_int.value) {
+                emm_ctx->security->knas_int.value = malloc(AUTH_KNAS_INT_SIZE);
+            } else {
+                AssertFatal(
+                    emm_ctx->security->knas_int.length >= AUTH_KNAS_INT_SIZE,
+                    " TODO realloc emm_ctx->security->knas_int OctetString");
+            }
+            emm_ctx->security->knas_int.length = AUTH_KNAS_INT_SIZE;
+            derive_key_nas(
+                NAS_INT_ALG,
+                emm_ctx->security->selected_algorithms.integrity,
+                emm_ctx->vector.kasme,
+                &emm_ctx->security->knas_int.value);
+
+            if ( ! emm_ctx->security->knas_enc.value) {
+                emm_ctx->security->knas_enc.value = malloc(AUTH_KNAS_ENC_SIZE);
+            } else {
+                AssertFatal(
+                    emm_ctx->security->knas_enc.length >= AUTH_KNAS_ENC_SIZE,
+                    " TODO realloc emm_ctx->security->knas_enc OctetString");
+            }
+            emm_ctx->security->knas_enc.length = AUTH_KNAS_ENC_SIZE;
+            derive_key_nas(
+                NAS_ENC_ALG,
+                emm_ctx->security->selected_algorithms.encryption,
+                emm_ctx->vector.kasme,
+                &emm_ctx->security->knas_enc.value);
 
             /* Set new security context indicator */
             security_context_is_new = TRUE;
@@ -434,6 +491,10 @@ 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->selected_eea = emm_ctx->security->selected_algorithms.encryption;
+        /* Set the EPS integrity algorithms to be replayed to the UE */
+        data->selected_eia = emm_ctx->security->selected_algorithms.integrity;
         /* Set the failure notification indicator */
         data->notify_failure = FALSE;
         /* Send security mode command message to the UE */
@@ -885,12 +946,14 @@ int _security_request(security_data_t *data, int is_new)
      * to the UE
      */
     emm_sap.primitive = EMMAS_SECURITY_REQ;
-    emm_sap.u.emm_as.u.security.guti = NULL;
-    emm_sap.u.emm_as.u.security.ueid = data->ueid;
-    emm_sap.u.emm_as.u.security.msgType = EMM_AS_MSG_TYPE_SMC;
-    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.guti         = NULL;
+    emm_sap.u.emm_as.u.security.ueid         = data->ueid;
+    emm_sap.u.emm_as.u.security.msgType      = EMM_AS_MSG_TYPE_SMC;
+    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.selected_eea = data->selected_eea;
+    emm_sap.u.emm_as.u.security.selected_eia = data->selected_eia;
 
 #if defined(EPC_BUILD)
     if (data->ueid > 0) {
@@ -976,5 +1039,64 @@ static int _security_abort(void *args)
     LOG_FUNC_RETURN (rc);
 }
 
+
+/****************************************************************************
+ **                                                                        **
+ ** Name:    _security_select_algorithms()                                 **
+ **                                                                        **
+ ** Description: Select int and enc algorithms based on UE capabilities and**
+ **      MME capabilities and MME preferences                              **
+ **                                                                        **
+ ** Inputs:  ue_eia:      integrity algorithms supported by UE             **
+ **          ue_eea:      ciphering algorithms supported by UE             **
+ **                                                                        **
+ ** Outputs: mme_eia:     integrity algorithms supported by MME            **
+ **          mme_eea:     ciphering algorithms supported by MME            **
+ **                                                                        **
+ **      Return:    RETURNok, RETURNerror                                  **
+ **      Others:    None                                                   **
+ **                                                                        **
+ ***************************************************************************/
+static int _security_select_algorithms(
+    const int   ue_eiaP,
+    const int   ue_eeaP,
+    int * const mme_eiaP,
+    int * const mme_eeaP)
+{
+    LOG_FUNC_IN;
+
+    int rc            = RETURNerror;
+
+    /* TODO work with loaded preferences from config file */
+
+    if (ue_eiaP & (0x80 >> NAS_SECURITY_ALGORITHMS_EIA2)) {
+        LOG_TRACE(DEBUG,"Selected  NAS_SECURITY_ALGORITHMS_EIA0");
+        *mme_eiaP = NAS_SECURITY_ALGORITHMS_EIA0;
+    } else if (ue_eiaP & (0x80 >> NAS_SECURITY_ALGORITHMS_EIA1)) {
+        LOG_TRACE(DEBUG,"Selected  NAS_SECURITY_ALGORITHMS_EIA1");
+        *mme_eiaP = NAS_SECURITY_ALGORITHMS_EIA1;
+    } else if (ue_eiaP & (0x80 >> NAS_SECURITY_ALGORITHMS_EIA0)) {
+        LOG_TRACE(DEBUG,"Selected  NAS_SECURITY_ALGORITHMS_EIA0");
+        *mme_eiaP = NAS_SECURITY_ALGORITHMS_EIA0;
+    } else {
+        LOG_FUNC_RETURN (rc);
+    }
+
+    if (ue_eeaP & (0x80 >> NAS_SECURITY_ALGORITHMS_EEA0)) {
+        LOG_TRACE(DEBUG,"Selected  NAS_SECURITY_ALGORITHMS_EEA0");
+        *mme_eeaP = NAS_SECURITY_ALGORITHMS_EEA0;
+    } else if (ue_eeaP & (0x80 >> NAS_SECURITY_ALGORITHMS_EEA2)) {
+        LOG_TRACE(DEBUG,"Selected  NAS_SECURITY_ALGORITHMS_EEA2");
+        *mme_eeaP = NAS_SECURITY_ALGORITHMS_EEA2;
+    } else if (ue_eeaP & (0x80 >> NAS_SECURITY_ALGORITHMS_EEA1)) {
+        LOG_TRACE(DEBUG,"Selected  NAS_SECURITY_ALGORITHMS_EEA1");
+        *mme_eeaP = NAS_SECURITY_ALGORITHMS_EEA1;
+    } else {
+        LOG_FUNC_RETURN (rc);
+    }
+
+    LOG_FUNC_RETURN (RETURNok);
+}
+
 #endif // NAS_MME
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h b/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h
index a15a664d06..afc061fb4e 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/emmData.h
@@ -113,6 +113,10 @@ typedef struct {
         UInt8_t encryption:4;   /* algorithm used for ciphering        */
         UInt8_t integrity:4;    /* algorithm used for integrity protection */
     } capability;       /* UE network capability           */
+    struct {
+        UInt8_t encryption:4;   /* algorithm used for ciphering           */
+        UInt8_t integrity:4;    /* algorithm used for integrity protection */
+    } selected_algorithms;       /* MME selected algorithms                */
 } emm_security_context_t;
 
 /*
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/msg/emm_cause.h b/openair-cn/NAS/EURECOM-NAS/src/emm/msg/emm_cause.h
index 8d7dc3cbe8..77f17f6889 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/msg/emm_cause.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/msg/emm_cause.h
@@ -67,7 +67,7 @@ Description	Defines error cause code returned upon receiving unknown,
 #define EMM_CAUSE_MAC_FAILURE			20
 #define EMM_CAUSE_SYNCH_FAILURE			21
 #define EMM_CAUSE_CONGESTION			22
-#define EMM_CAUSE_UE_SECURITY_MISMATCH		23 
+#define EMM_CAUSE_UE_SECURITY_MISMATCH		23
 #define EMM_CAUSE_SECURITY_MODE_REJECTED	24
 #define EMM_CAUSE_NON_EPS_AUTH_UNACCEPTABLE	26
 #define EMM_CAUSE_CS_SERVICE_NOT_AVAILABLE	39
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 37b39b1143..9315bc4abd 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
@@ -105,9 +105,20 @@ static int _emm_as_data_ind(const emm_as_data_t *msg, int *emm_cause);
  */
 static EMM_msg *_emm_as_set_header(nas_message_t *msg,
                                    const emm_as_security_data_t *security);
-static int _emm_as_encode(as_nas_info_t *info, nas_message_t *msg, int length);
-static int _emm_as_encrypt(as_nas_info_t *info,
-                           const nas_message_security_header_t *header, const char *buffer, int length);
+static int
+_emm_as_encode(
+    as_nas_info_t *info,
+    nas_message_t *msg,
+    int length,
+    emm_security_context_t     *emm_security_context);
+
+static int _emm_as_encrypt(
+    as_nas_info_t *info,
+    const nas_message_security_header_t *header,
+    const char *buffer,
+    int length,
+    emm_security_context_t *emm_security_context);
+
 static int _emm_as_send(const emm_as_t *msg);
 
 #ifdef NAS_UE
@@ -310,8 +321,22 @@ static int _emm_as_recv(unsigned int ueid, const char *msg, int len,
     nas_message_t nas_msg;
     memset(&nas_msg, 0 , sizeof(nas_message_t));
 
+    emm_data_context_t           *emm_ctx  = NULL;
+    emm_security_context_t       *security = NULL;    /* Current EPS NAS security context     */
+
+#if defined(EPC_BUILD)
+    emm_ctx = emm_data_context_get(&_emm_data, ueid);
+    if (emm_ctx) {
+        security = emm_ctx->security;
+    }
+#else
+    if (ueid < EMM_DATA_NB_UE_MAX) {
+        emm_ctx = _emm_data.ctx[ueid];
+    }
+#endif
+
     /* Decode the received message */
-    decoder_rc = nas_message_decode(msg, &nas_msg, len);
+    decoder_rc = nas_message_decode(msg, &nas_msg, len, security);
 
     if (decoder_rc < 0) {
         LOG_TRACE(WARNING, "EMMAS-SAP - Failed to decode NAS message "
@@ -369,33 +394,38 @@ static int _emm_as_recv(unsigned int ueid, const char *msg, int len,
 #endif
 #ifdef NAS_MME
         case ATTACH_REQUEST:
-            rc = emm_recv_attach_request(ueid,
-                                         &emm_msg->attach_request,
-                                         emm_cause);
+            rc = emm_recv_attach_request(
+                ueid,
+                &emm_msg->attach_request,
+                emm_cause);
             break;
 
         case IDENTITY_RESPONSE:
-            rc = emm_recv_identity_response(ueid,
-                                            &emm_msg->identity_response,
-                                            emm_cause);
+            rc = emm_recv_identity_response(
+                ueid,
+                &emm_msg->identity_response,
+                emm_cause);
             break;
 
         case AUTHENTICATION_RESPONSE:
-            rc = emm_recv_authentication_response(ueid,
-                                                  &emm_msg->authentication_response,
-                                                  emm_cause);
+            rc = emm_recv_authentication_response(
+                ueid,
+                &emm_msg->authentication_response,
+                emm_cause);
             break;
 
         case AUTHENTICATION_FAILURE:
-            rc = emm_recv_authentication_failure(ueid,
-                                                 &emm_msg->authentication_failure,
-                                                 emm_cause);
+            rc = emm_recv_authentication_failure(
+                ueid,
+                &emm_msg->authentication_failure,
+                emm_cause);
             break;
 
         case SECURITY_MODE_COMPLETE:
-            rc = emm_recv_security_mode_complete(ueid,
-                                                 &emm_msg->security_mode_complete,
-                                                 emm_cause);
+            rc = emm_recv_security_mode_complete(
+                ueid,
+                &emm_msg->security_mode_complete,
+                emm_cause);
             break;
 
         case SECURITY_MODE_REJECT:
@@ -464,10 +494,32 @@ static int _emm_as_data_ind(const emm_as_data_t *msg, int *emm_cause)
             char *plain_msg = (char *)malloc(msg->NASmsg.length);
             if (plain_msg) {
                 nas_message_security_header_t header;
+                emm_data_context_t           *emm_ctx  = NULL;
+                emm_security_context_t       *security = NULL;    /* Current EPS NAS security context     */
+
+                memset(&header, 0, sizeof(header));
                 /* Decrypt the received security protected message */
+#if defined(EPC_BUILD)
+                if (msg->ueid > 0) {
+                    emm_ctx = emm_data_context_get(&_emm_data, msg->ueid);
+                    if (emm_ctx) {
+                        security = emm_ctx->security;
+                    }
+                }
+#else
+                if (msg->ueid < EMM_DATA_NB_UE_MAX) {
+                    emm_ctx = _emm_data.ctx[msg->ueid];
+                    if (emm_ctx) {
+                        security = emm_ctx->security;
+                    }
+                }
+#endif
                 int bytes = nas_message_decrypt((char *)(msg->NASmsg.value),
-                                                plain_msg, &header,
-                                                msg->NASmsg.length);
+                                                plain_msg,
+                                                &header,
+                                                msg->NASmsg.length,
+                                                security
+                                                );
                 if (bytes < 0) {
                     /* Failed to decrypt the message */
                     *emm_cause = EMM_CAUSE_PROTOCOL_ERROR;
@@ -694,6 +746,8 @@ static int _emm_as_establish_req(const emm_as_establish_t *msg, int *emm_cause)
 {
     LOG_FUNC_IN;
 
+    struct emm_data_context_s *emm_ctx                = NULL;
+    emm_security_context_t    *emm_security_context   = NULL;
     int decoder_rc;
     int rc = RETURNerror;
 
@@ -702,9 +756,23 @@ static int _emm_as_establish_req(const emm_as_establish_t *msg, int *emm_cause)
     nas_message_t nas_msg;
     memset(&nas_msg, 0 , sizeof(nas_message_t));
 
+#if defined(EPC_BUILD)
+    emm_ctx = emm_data_context_get(&_emm_data, msg->ueid);
+#else
+    if (msg->ueid < EMM_DATA_NB_UE_MAX) {
+        emm_ctx = _emm_data.ctx[msg->ueid];
+    }
+#endif
+    if (emm_ctx) {
+        emm_security_context = emm_ctx->security;
+    }
+
     /* Decode initial NAS message */
-    decoder_rc = nas_message_decode((char *)(msg->NASmsg.value), &nas_msg,
-                                    msg->NASmsg.length);
+    decoder_rc = nas_message_decode(
+        (char *)(msg->NASmsg.value),
+        &nas_msg,
+        msg->NASmsg.length,
+        emm_security_context);
 
     if (decoder_rc < TLV_DECODE_FATAL_ERROR) {
         *emm_cause = EMM_CAUSE_PROTOCOL_ERROR;
@@ -719,8 +787,10 @@ static int _emm_as_establish_req(const emm_as_establish_t *msg, int *emm_cause)
     EMM_msg *emm_msg = &nas_msg.plain.emm;
     switch (emm_msg->header.message_type) {
         case ATTACH_REQUEST:
-            rc = emm_recv_attach_request(msg->ueid, &emm_msg->attach_request,
-                                         emm_cause);
+            rc = emm_recv_attach_request(
+                msg->ueid,
+                &emm_msg->attach_request,
+                emm_cause);
             break;
 
         case DETACH_REQUEST:
@@ -728,9 +798,10 @@ static int _emm_as_establish_req(const emm_as_establish_t *msg, int *emm_cause)
             break;
 
         case TRACKING_AREA_UPDATE_REQUEST:
-            rc = emm_recv_tracking_area_update_request(msg->ueid,
-                                                       &emm_msg->tracking_area_update_request,
-                                                       emm_cause);
+            rc = emm_recv_tracking_area_update_request(
+                msg->ueid,
+                &emm_msg->tracking_area_update_request,
+                emm_cause);
             break;
 
         case SERVICE_REQUEST:
@@ -919,13 +990,19 @@ static EMM_msg *_emm_as_set_header(nas_message_t *msg,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _emm_as_encode(as_nas_info_t *info, nas_message_t *msg, int length)
+static int
+_emm_as_encode(
+    as_nas_info_t              *info,
+    nas_message_t              *msg,
+    int                         length,
+    emm_security_context_t     *emm_security_context)
 {
     LOG_FUNC_IN;
 
     int bytes = 0;
 
-    if (msg->header.security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED) {
+    if (msg->header.security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED)
+    {
         emm_msg_header_t *header = &msg->security_protected.plain.emm.header;
         /* Expand size of protected NAS message */
         length += NAS_MESSAGE_SECURITY_HEADER_SIZE;
@@ -937,7 +1014,12 @@ static int _emm_as_encode(as_nas_info_t *info, nas_message_t *msg, int length)
     info->data = (Byte_t *)malloc(length * sizeof(Byte_t));
     if (info->data != NULL) {
         /* Encode the NAS message */
-        bytes = nas_message_encode((char *)(info->data), msg, length);
+        bytes = nas_message_encode(
+            (char *)(info->data),
+            msg,
+            length,
+            emm_security_context);
+
         if (bytes > 0) {
             info->length = bytes;
         } else {
@@ -966,9 +1048,13 @@ static int _emm_as_encode(as_nas_info_t *info, nas_message_t *msg, int length)
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-static int _emm_as_encrypt(as_nas_info_t *info,
-                           const nas_message_security_header_t *header,
-                           const char *msg, int length)
+static int
+_emm_as_encrypt(
+    as_nas_info_t *info,
+    const nas_message_security_header_t *header,
+    const char *msg,
+    int length,
+    emm_security_context_t *emm_security_context)
 {
     LOG_FUNC_IN;
 
@@ -982,7 +1068,13 @@ static int _emm_as_encrypt(as_nas_info_t *info,
     info->data = (Byte_t *)malloc(length * sizeof(Byte_t));
     if (info->data != NULL) {
         /* Encrypt the NAS information message */
-        bytes = nas_message_encrypt(msg, (char *)(info->data), header, length);
+        bytes = nas_message_encrypt(
+            msg,
+            (char *)(info->data),
+            header,
+            length,
+            emm_security_context);
+
         if (bytes > 0) {
             info->length = bytes;
         } else {
@@ -1020,51 +1112,60 @@ static int _emm_as_send(const emm_as_t *msg)
 
     switch (msg->primitive) {
         case _EMMAS_DATA_REQ:
-            as_msg.msgID = _emm_as_data_req(&msg->u.data,
-                                            &as_msg.msg.ul_info_transfer_req);
+            as_msg.msgID = _emm_as_data_req(
+                &msg->u.data,
+                &as_msg.msg.ul_info_transfer_req);
             break;
 
         case _EMMAS_STATUS_IND:
-            as_msg.msgID = _emm_as_status_ind(&msg->u.status,
-                                              &as_msg.msg.ul_info_transfer_req);
+            as_msg.msgID = _emm_as_status_ind(
+                &msg->u.status,
+                &as_msg.msg.ul_info_transfer_req);
             break;
 
         case _EMMAS_RELEASE_REQ:
-            as_msg.msgID = _emm_as_release_req(&msg->u.release,
-                                               &as_msg.msg.nas_release_req);
+            as_msg.msgID = _emm_as_release_req(
+                &msg->u.release,
+                &as_msg.msg.nas_release_req);
             break;
 
 #ifdef NAS_UE
         case _EMMAS_SECURITY_RES:
-            as_msg.msgID = _emm_as_security_res(&msg->u.security,
-                                                &as_msg.msg.ul_info_transfer_req);
+            as_msg.msgID = _emm_as_security_res(
+                &msg->u.security,
+                &as_msg.msg.ul_info_transfer_req);
             break;
 
         case _EMMAS_ESTABLISH_REQ:
-            as_msg.msgID = _emm_as_establish_req(&msg->u.establish,
-                                                 &as_msg.msg.nas_establish_req);
+            as_msg.msgID = _emm_as_establish_req(
+                &msg->u.establish,
+                &as_msg.msg.nas_establish_req);
             break;
 
 #endif
 #ifdef NAS_MME
         case _EMMAS_SECURITY_REQ:
-            as_msg.msgID = _emm_as_security_req(&msg->u.security,
-                                                &as_msg.msg.dl_info_transfer_req);
+            as_msg.msgID = _emm_as_security_req(
+                &msg->u.security,
+                &as_msg.msg.dl_info_transfer_req);
             break;
 
         case _EMMAS_SECURITY_REJ:
-            as_msg.msgID = _emm_as_security_rej(&msg->u.security,
-                                                &as_msg.msg.dl_info_transfer_req);
+            as_msg.msgID = _emm_as_security_rej(
+                &msg->u.security,
+                &as_msg.msg.dl_info_transfer_req);
             break;
 
         case _EMMAS_ESTABLISH_CNF:
-            as_msg.msgID = _emm_as_establish_cnf(&msg->u.establish,
-                                                 &as_msg.msg.nas_establish_rsp);
+            as_msg.msgID = _emm_as_establish_cnf(
+                &msg->u.establish,
+                &as_msg.msg.nas_establish_rsp);
             break;
 
         case _EMMAS_ESTABLISH_REJ:
-            as_msg.msgID = _emm_as_establish_rej(&msg->u.establish,
-                                                 &as_msg.msg.nas_establish_rsp);
+            as_msg.msgID = _emm_as_establish_rej(
+                &msg->u.establish,
+                &as_msg.msg.nas_establish_rsp);
             break;
 
         case _EMMAS_PAGE_IND:
@@ -1098,25 +1199,28 @@ static int _emm_as_send(const emm_as_t *msg)
 
         switch (as_msg.msgID) {
             case AS_DL_INFO_TRANSFER_REQ: {
-                nas_itti_dl_data_req(as_msg.msg.dl_info_transfer_req.UEid,
-                                     as_msg.msg.dl_info_transfer_req.nasMsg.data,
-                                     as_msg.msg.dl_info_transfer_req.nasMsg.length);
+                nas_itti_dl_data_req(
+                    as_msg.msg.dl_info_transfer_req.UEid,
+                    as_msg.msg.dl_info_transfer_req.nasMsg.data,
+                    as_msg.msg.dl_info_transfer_req.nasMsg.length);
                 LOG_FUNC_RETURN (RETURNok);
             } break;
 
             case AS_NAS_ESTABLISH_RSP:
             case AS_NAS_ESTABLISH_CNF: {
                 if (as_msg.msg.nas_establish_rsp.errCode != AS_SUCCESS) {
-                    nas_itti_dl_data_req(as_msg.msg.nas_establish_rsp.UEid,
-                                         as_msg.msg.nas_establish_rsp.nasMsg.data,
-                                         as_msg.msg.nas_establish_rsp.nasMsg.length);
+                    nas_itti_dl_data_req(
+                        as_msg.msg.nas_establish_rsp.UEid,
+                        as_msg.msg.nas_establish_rsp.nasMsg.data,
+                        as_msg.msg.nas_establish_rsp.nasMsg.length);
                     LOG_FUNC_RETURN (RETURNok);
                 } else {
                     /* Handle success case */
-                    nas_itti_establish_cnf(as_msg.msg.nas_establish_rsp.UEid,
-                                           as_msg.msg.nas_establish_rsp.errCode,
-                                           as_msg.msg.nas_establish_rsp.nasMsg.data,
-                                           as_msg.msg.nas_establish_rsp.nasMsg.length);
+                    nas_itti_establish_cnf(
+                        as_msg.msg.nas_establish_rsp.UEid,
+                        as_msg.msg.nas_establish_rsp.errCode,
+                        as_msg.msg.nas_establish_rsp.nasMsg.data,
+                        as_msg.msg.nas_establish_rsp.nasMsg.length);
                     LOG_FUNC_RETURN (RETURNok);
                 }
             } break;
@@ -1134,32 +1238,36 @@ static int _emm_as_send(const emm_as_t *msg)
 
         switch (as_msg.msgID) {
             case AS_CELL_INFO_REQ: {
-                nas_itti_cell_info_req(as_msg.msg.cell_info_req.plmnID,
-                                       as_msg.msg.cell_info_req.rat);
+                nas_itti_cell_info_req(
+                    as_msg.msg.cell_info_req.plmnID,
+                    as_msg.msg.cell_info_req.rat);
                 LOG_FUNC_RETURN (RETURNok);
             } break;
 
             case AS_NAS_ESTABLISH_REQ: {
-                nas_itti_nas_establish_req(as_msg.msg.nas_establish_req.cause,
-                                           as_msg.msg.nas_establish_req.type,
-                                           as_msg.msg.nas_establish_req.s_tmsi,
-                                           as_msg.msg.nas_establish_req.plmnID,
-                                           as_msg.msg.nas_establish_req.initialNasMsg.data,
-                                           as_msg.msg.nas_establish_req.initialNasMsg.length);
+                nas_itti_nas_establish_req(
+                    as_msg.msg.nas_establish_req.cause,
+                    as_msg.msg.nas_establish_req.type,
+                    as_msg.msg.nas_establish_req.s_tmsi,
+                    as_msg.msg.nas_establish_req.plmnID,
+                    as_msg.msg.nas_establish_req.initialNasMsg.data,
+                    as_msg.msg.nas_establish_req.initialNasMsg.length);
                 LOG_FUNC_RETURN (RETURNok);
             } break;
 
             case AS_UL_INFO_TRANSFER_REQ: {
-                nas_itti_ul_data_req(as_msg.msg.ul_info_transfer_req.UEid,
-                                     as_msg.msg.ul_info_transfer_req.nasMsg.data,
-                                     as_msg.msg.ul_info_transfer_req.nasMsg.length);
+                nas_itti_ul_data_req(
+                    as_msg.msg.ul_info_transfer_req.UEid,
+                    as_msg.msg.ul_info_transfer_req.nasMsg.data,
+                    as_msg.msg.ul_info_transfer_req.nasMsg.length);
                 LOG_FUNC_RETURN (RETURNok);
             } break;
 
             case AS_RAB_ESTABLISH_RSP: {
-                nas_itti_rab_establish_rsp(as_msg.msg.rab_establish_rsp.s_tmsi,
-                                           as_msg.msg.rab_establish_rsp.rabID,
-                                           as_msg.msg.rab_establish_rsp.errCode);
+                nas_itti_rab_establish_rsp(
+                    as_msg.msg.rab_establish_rsp.s_tmsi,
+                    as_msg.msg.rab_establish_rsp.rabID,
+                    as_msg.msg.rab_establish_rsp.errCode);
                 LOG_FUNC_RETURN (RETURNok);
             } break;
 
@@ -1245,13 +1353,32 @@ static int _emm_as_data_req(const emm_as_data_t *msg,
 
     if (size > 0) {
         int bytes;
+        struct emm_data_context_s *emm_ctx                = NULL;
+        emm_security_context_t    *emm_security_context   = NULL;
+#if defined(EPC_BUILD)
+        emm_ctx = emm_data_context_get(&_emm_data, msg->ueid);
+#else
+        if (msg->ueid < EMM_DATA_NB_UE_MAX) {
+            emm_ctx = _emm_data.ctx[msg->ueid];
+        }
+#endif
+        if (emm_ctx) {
+            emm_security_context = emm_ctx->security;
+        }
+
         if (!is_encoded) {
             /* Encode the NAS information message */
-            bytes = _emm_as_encode(&as_msg->nasMsg, &nas_msg, size);
+            bytes = _emm_as_encode(&as_msg->nasMsg,
+                &nas_msg,
+                size,
+                emm_security_context);
         } else {
             /* Encrypt the NAS information message */
-            bytes = _emm_as_encrypt(&as_msg->nasMsg, &nas_msg.header,
-                                    (char *)(msg->NASmsg.value), size);
+            bytes = _emm_as_encrypt(&as_msg->nasMsg,
+                &nas_msg.header,
+                (char *)(msg->NASmsg.value),
+                size,
+                emm_security_context);
         }
         if (bytes > 0) {
 #ifdef NAS_UE
@@ -1311,8 +1438,25 @@ static int _emm_as_status_ind(const emm_as_status_t *msg,
     }
 
     if (size > 0) {
+        struct emm_data_context_s *emm_ctx                = NULL;
+        emm_security_context_t    *emm_security_context   = NULL;
+#if defined(EPC_BUILD)
+        emm_ctx = emm_data_context_get(&_emm_data, msg->ueid);
+#else
+        if (msg->ueid < EMM_DATA_NB_UE_MAX) {
+            emm_ctx = _emm_data.ctx[msg->ueid];
+        }
+#endif
+        if (emm_ctx) {
+            emm_security_context = emm_ctx->security;
+        }
         /* Encode the NAS information message */
-        int bytes = _emm_as_encode(&as_msg->nasMsg, &nas_msg, size);
+        int bytes = _emm_as_encode(
+            &as_msg->nasMsg,
+            &nas_msg,
+            size,
+            emm_security_context);
+
         if (bytes > 0) {
 #ifdef NAS_UE
             LOG_FUNC_RETURN (AS_UL_INFO_TRANSFER_REQ);
@@ -1407,26 +1551,32 @@ static int _emm_as_security_res(const emm_as_security_t *msg,
     /* Setup the NAS security message */
     if (emm_msg != NULL) switch (msg->msgType) {
             case EMM_AS_MSG_TYPE_IDENT:
-                size = emm_send_identity_response(msg, &emm_msg->identity_response);
+                size = emm_send_identity_response(
+                    msg,
+                    &emm_msg->identity_response);
                 break;
 
             case EMM_AS_MSG_TYPE_AUTH:
                 if (msg->emm_cause != EMM_CAUSE_SUCCESS) {
-                    size = emm_send_authentication_failure(msg,
-                                                           &emm_msg->authentication_failure);
+                    size = emm_send_authentication_failure(
+                        msg,
+                        &emm_msg->authentication_failure);
                 } else {
-                    size = emm_send_authentication_response(msg,
-                                                            &emm_msg->authentication_response);
+                    size = emm_send_authentication_response(
+                        msg,
+                        &emm_msg->authentication_response);
                 }
                 break;
 
             case EMM_AS_MSG_TYPE_SMC:
                 if (msg->emm_cause != EMM_CAUSE_SUCCESS) {
-                    size = emm_send_security_mode_reject(msg,
-                                                         &emm_msg->security_mode_reject);
+                    size = emm_send_security_mode_reject(
+                        msg,
+                        &emm_msg->security_mode_reject);
                 } else {
-                    size = emm_send_security_mode_complete(msg,
-                                                           &emm_msg->security_mode_complete);
+                    size = emm_send_security_mode_complete(
+                        msg,
+                        &emm_msg->security_mode_complete);
                 }
                 break;
 
@@ -1497,21 +1647,22 @@ static int _emm_as_establish_req(const emm_as_establish_t *msg,
 
             case EMM_AS_NAS_INFO_DETACH:
                 size = emm_send_initial_detach_request(msg,
-                                                       &emm_msg->detach_request);
+                    &emm_msg->detach_request);
                 break;
 
             case EMM_AS_NAS_INFO_TAU:
                 size = emm_send_initial_tau_request(msg,
-                                                    &emm_msg->tracking_area_update_request);
+                    &emm_msg->tracking_area_update_request);
                 break;
 
             case EMM_AS_NAS_INFO_SR:
-                size = emm_send_initial_sr_request(msg, &emm_msg->service_request);
+                size = emm_send_initial_sr_request(msg,
+                    &emm_msg->service_request);
                 break;
 
             case EMM_AS_NAS_INFO_EXTSR:
                 size = emm_send_initial_extsr_request(msg,
-                                                      &emm_msg->extended_service_request);
+                    &emm_msg->extended_service_request);
                 break;
 
             default:
@@ -1574,17 +1725,18 @@ static int _emm_as_security_req(const emm_as_security_t *msg,
     /* Setup the NAS security message */
     if (emm_msg != NULL) switch (msg->msgType) {
             case EMM_AS_MSG_TYPE_IDENT:
-                size = emm_send_identity_request(msg, &emm_msg->identity_request);
+                size = emm_send_identity_request(msg,
+                    &emm_msg->identity_request);
                 break;
 
             case EMM_AS_MSG_TYPE_AUTH:
                 size = emm_send_authentication_request(msg,
-                                                       &emm_msg->authentication_request);
+                    &emm_msg->authentication_request);
                 break;
 
             case EMM_AS_MSG_TYPE_SMC:
                 size = emm_send_security_mode_command(msg,
-                                                      &emm_msg->security_mode_command);
+                    &emm_msg->security_mode_command);
                 break;
 
             default:
@@ -1593,8 +1745,25 @@ static int _emm_as_security_req(const emm_as_security_t *msg,
         }
 
     if (size > 0) {
+        struct emm_data_context_s *emm_ctx                = NULL;
+        emm_security_context_t    *emm_security_context   = NULL;
+#if defined(EPC_BUILD)
+        emm_ctx = emm_data_context_get(&_emm_data, msg->ueid);
+#else
+        if (msg->ueid < EMM_DATA_NB_UE_MAX) {
+            emm_ctx = _emm_data.ctx[msg->ueid];
+        }
+#endif
+        if (emm_ctx) {
+            emm_security_context = emm_ctx->security;
+        }
         /* Encode the NAS security message */
-        int bytes = _emm_as_encode(&as_msg->nasMsg, &nas_msg, size);
+        int bytes = _emm_as_encode(
+            &as_msg->nasMsg,
+            &nas_msg,
+            size,
+            emm_security_context);
+
         if (bytes > 0) {
             LOG_FUNC_RETURN (AS_DL_INFO_TRANSFER_REQ);
         }
@@ -1654,8 +1823,25 @@ static int _emm_as_security_rej(const emm_as_security_t *msg,
         }
 
     if (size > 0) {
+        struct emm_data_context_s *emm_ctx                = NULL;
+        emm_security_context_t    *emm_security_context   = NULL;
+#if defined(EPC_BUILD)
+        emm_ctx = emm_data_context_get(&_emm_data, msg->ueid);
+#else
+        if (msg->ueid < EMM_DATA_NB_UE_MAX) {
+            emm_ctx = _emm_data.ctx[msg->ueid];
+        }
+#endif
+        if (emm_ctx) {
+            emm_security_context = emm_ctx->security;
+        }
         /* Encode the NAS security message */
-        int bytes = _emm_as_encode(&as_msg->nasMsg, &nas_msg, size);
+        int bytes = _emm_as_encode(
+            &as_msg->nasMsg,
+            &nas_msg,
+            size,
+            emm_security_context);
+
         if (bytes > 0) {
             LOG_FUNC_RETURN (AS_DL_INFO_TRANSFER_REQ);
         }
@@ -1708,8 +1894,9 @@ static int _emm_as_establish_cnf(const emm_as_establish_t *msg,
     /* Setup the initial NAS information message */
     if (emm_msg != NULL) switch (msg->NASinfo) {
             case EMM_AS_NAS_INFO_ATTACH:
-                LOG_TRACE(WARNING, "EMMAS-SAP - emm_as_establish.nasMSG.length"\
-                          "=%d", msg->NASmsg.length);
+                LOG_TRACE(WARNING,
+                    "EMMAS-SAP - emm_as_establish.nasMSG.length=%d",
+                    msg->NASmsg.length);
                 size = emm_send_attach_accept(msg, &emm_msg->attach_accept);
                 break;
 
@@ -1720,8 +1907,32 @@ static int _emm_as_establish_cnf(const emm_as_establish_t *msg,
         }
 
     if (size > 0) {
+        struct emm_data_context_s *emm_ctx                = NULL;
+        emm_security_context_t    *emm_security_context   = NULL;
+#if defined(EPC_BUILD)
+        emm_ctx = emm_data_context_get(&_emm_data, msg->ueid);
+#else
+        if (msg->ueid < EMM_DATA_NB_UE_MAX) {
+            emm_ctx = _emm_data.ctx[msg->ueid];
+        }
+#endif
+        if (emm_ctx) {
+            emm_security_context = emm_ctx->security;
+            if (emm_security_context) {
+                as_msg->nas_ul_count = 0x00000000 |
+                                       (emm_security_context->ul_count.overflow << 8) |
+                                       emm_security_context->ul_count.seq_num;
+                LOG_TRACE(DEBUG, "EMMAS-SAP - NAS UL COUNT %8x",
+                    as_msg->nas_ul_count);
+            }
+        }
         /* Encode the initial NAS information message */
-        int bytes = _emm_as_encode(&as_msg->nasMsg, &nas_msg, size);
+        int bytes = _emm_as_encode(
+            &as_msg->nasMsg,
+            &nas_msg,
+            size,
+            emm_security_context);
+
         if (bytes > 0) {
             as_msg->errCode = AS_SUCCESS;
             LOG_FUNC_RETURN (AS_NAS_ESTABLISH_CNF);
@@ -1780,7 +1991,8 @@ static int _emm_as_establish_rej(const emm_as_establish_t *msg,
                 break;
 
             case EMM_AS_NAS_INFO_TAU:
-                size = emm_send_tracking_area_update_reject(msg, &emm_msg->tracking_area_update_reject);
+                size = emm_send_tracking_area_update_reject(msg,
+                    &emm_msg->tracking_area_update_reject);
                 break;
 
             default:
@@ -1790,8 +2002,24 @@ static int _emm_as_establish_rej(const emm_as_establish_t *msg,
         }
 
     if (size > 0) {
+        struct emm_data_context_s *emm_ctx                = NULL;
+        emm_security_context_t    *emm_security_context   = NULL;
+#if defined(EPC_BUILD)
+        emm_ctx = emm_data_context_get(&_emm_data, msg->ueid);
+#else
+        if (msg->ueid < EMM_DATA_NB_UE_MAX) {
+            emm_ctx = _emm_data.ctx[msg->ueid];
+        }
+#endif
+        if (emm_ctx) {
+            emm_security_context = emm_ctx->security;
+        }
         /* Encode the initial NAS information message */
-        int bytes = _emm_as_encode(&as_msg->nasMsg, &nas_msg, size);
+        int bytes = _emm_as_encode(
+            &as_msg->nasMsg,
+            &nas_msg,
+            size,
+            emm_security_context);
         if (bytes > 0) {
             as_msg->errCode = AS_TERMINATED_NAS;
             LOG_FUNC_RETURN (AS_NAS_ESTABLISH_RSP);
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 b5171339da..eaa0a943f4 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
@@ -98,6 +98,10 @@ typedef struct {
     UInt8_t eea;        /* Replayed EPS encryption algorithms   */
     UInt8_t eia;        /* Replayed EPS integrity algorithms    */
 
+    // Added by LG
+    UInt8_t selected_eea; /* Selected EPS encryption algorithms   */
+    UInt8_t selected_eia; /* Selected EPS integrity algorithms    */
+
 #define EMM_AS_MSG_TYPE_IDENT   0x01    /* Identification message   */
 #define EMM_AS_MSG_TYPE_AUTH    0x02    /* Authentication message   */
 #define EMM_AS_MSG_TYPE_SMC 0x03    /* Security Mode Command    */
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.c b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.c
index b44b3cc174..ddc005f0c1 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.c
@@ -101,11 +101,14 @@ static int _emm_cn_authentication_res(const emm_cn_auth_res_t *msg)
      * and NAS security setup to activate integrity protection and NAS
      * ciphering are mandatory.
      */
-    rc = emm_proc_authentication(emm_ctx, emm_ctx->ueid, 0, // TODO: eksi != 0
-                                 &loc_rand, &autn,
-                                 emm_attach_security,
-                                 NULL,
-                                 NULL);
+    rc = emm_proc_authentication(emm_ctx,
+        emm_ctx->ueid,
+        0, // TODO: eksi != 0
+        &loc_rand,
+        &autn,
+        emm_attach_security,
+        NULL,
+        NULL);
     if (rc != RETURNok) {
         /* Failed to initiate the authentication procedure */
         LOG_TRACE(WARNING, "EMM-PROC  - "
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 dcd5ad4692..2b3f69507b 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
@@ -983,9 +983,11 @@ int emm_recv_authentication_failure(unsigned int ueid,
  **      Others:    None                                       **
  **                                                                        **
  ***************************************************************************/
-int emm_recv_security_mode_complete(unsigned int ueid,
-                                    security_mode_complete_msg *msg,
-                                    int *emm_cause)
+int
+emm_recv_security_mode_complete(
+    unsigned int                ueid,
+    security_mode_complete_msg *msg,
+    int                        *emm_cause)
 {
     LOG_FUNC_IN;
 
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 68703ff0c4..7401ef6fda 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
@@ -1205,9 +1205,9 @@ int emm_send_security_mode_command(const emm_as_security_t *msg,
     /* Selected NAS security algorithms */
     size += NAS_SECURITY_ALGORITHMS_MAXIMUM_LENGTH;
     emm_msg->selectednassecurityalgorithms.typeofcipheringalgorithm =
-        NAS_SECURITY_ALGORITHMS_EEA0;
+        msg->selected_eea;
     emm_msg->selectednassecurityalgorithms.typeofintegrityalgorithm =
-        NAS_SECURITY_ALGORITHMS_EIA0;
+        msg->selected_eia;
 
     /* NAS key set identifier */
     size += NAS_KEY_SET_IDENTIFIER_MAXIMUM_LENGTH;
diff --git a/openair-cn/NAS/EURECOM-NAS/src/include/securityDef.h b/openair-cn/NAS/EURECOM-NAS/src/include/securityDef.h
index 605f14b71b..3e75f04732 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/include/securityDef.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/include/securityDef.h
@@ -48,8 +48,8 @@ Description Contains global security definitions
 #define AUTH_RES_SIZE   16 /* Authentication response:      128 bits */
 #define AUTH_SNID_SIZE  3  /* Serving network's identity:   24 bits  */
 #define AUTH_KASME_SIZE 32 /* KASME security key:        256 bits    */
-#define AUTH_KNAS_INT_SIZE  AUTH_KASME_SIZE /* NAS integrity key     */
-#define AUTH_KNAS_ENC_SIZE  AUTH_KASME_SIZE /* NAS cyphering key     */
+#define AUTH_KNAS_INT_SIZE  16 /* NAS integrity key     */
+#define AUTH_KNAS_ENC_SIZE  16 /* NAS cyphering key     */
 #define AUTH_KENB_SIZE      AUTH_KASME_SIZE /* eNodeB security key   */
 
 /* "Separation bit" of AMF field */
diff --git a/openair-cn/NAS/EURECOM-NAS/tst/as_simulator/nas_process.c b/openair-cn/NAS/EURECOM-NAS/tst/as_simulator/nas_process.c
index 2dac50c923..de4a66f3af 100644
--- a/openair-cn/NAS/EURECOM-NAS/tst/as_simulator/nas_process.c
+++ b/openair-cn/NAS/EURECOM-NAS/tst/as_simulator/nas_process.c
@@ -98,10 +98,15 @@ static int _esm_status(char* buffer, int length, const esm_status_msg* msg);
 
 /*
  *----------------------------------------------------------------------------- 
- *				Process NAS message
+ *                              Process NAS message
  *----------------------------------------------------------------------------- 
  */
-int nas_process(char* buffer, int length, const char* msg, int size)
+int
+nas_process(
+    char* buffer,
+    int length,
+    const char* msg,
+    int size)
 {
     int index = 0;
     int bytes;
@@ -111,26 +116,28 @@ int nas_process(char* buffer, int length, const char* msg, int size)
     memset(&nas_msg, 0, sizeof(nas_message_t));
     bytes = nas_message_decode(msg, &nas_msg, size);
     if (bytes < 0) {
-	printf("ERROR\t: %s - Failed to decode NAS message (err=%d)\n",
-	       __FUNCTION__, bytes);
-	return (RETURNerror);
+        printf("ERROR\t: %s - Failed to decode NAS message (err=%d)\n",
+            __FUNCTION__, bytes);
+        return (RETURNerror);
     }
 
     int protocol_discriminator = nas_msg.header.protocol_discriminator;
     if (protocol_discriminator == EPS_MOBILITY_MANAGEMENT_MESSAGE) {
-	/* Process EPS Mobility Management NAS message */
-	index += _nas_process_emm(buffer + index, length - index,
-				  &nas_msg.plain.emm);
+        /* Process EPS Mobility Management NAS message */
+        index += _nas_process_emm(buffer + index,
+            length - index,
+            &nas_msg.plain.emm);
     }
     else if (protocol_discriminator == EPS_SESSION_MANAGEMENT_MESSAGE) {
-	/* Process EPS Session Management NAS message */
-	index += _nas_process_esm(buffer + index, length - index,
-				 &nas_msg.plain.esm);
+        /* Process EPS Session Management NAS message */
+        index += _nas_process_esm(buffer + index,
+            length - index,
+            &nas_msg.plain.esm);
     }
     else {
-	printf("ERROR\t: %s - Protocol discriminator is not valid (%d)\n",
-	       __FUNCTION__, protocol_discriminator);
-	return (RETURNerror);
+        printf("ERROR\t: %s - Protocol discriminator is not valid (%d)\n",
+            __FUNCTION__, protocol_discriminator);
+        return (RETURNerror);
     }
 
     buffer[index] = '\0';
@@ -150,116 +157,121 @@ int nas_process(char* buffer, int length, const char* msg, int size)
 
 /*
  *----------------------------------------------------------------------------- 
- *		    Process EPS Mobility Management NAS message
+ *                  Process EPS Mobility Management NAS message
  *----------------------------------------------------------------------------- 
  */
-static int _nas_process_emm(char* buffer, int length, const EMM_msg* msg)
+static int
+_nas_process_emm(
+    char* buffer,
+    int length,
+    const EMM_msg* msg)
 {
     int index = 0;
     const EsmMessageContainer* esm_container = NULL;
 
     printf("INFO\t: Process %s\n", emmMsgType(msg->header.message_type));
     index += snprintf(buffer + index, length - index, "%s (",
-		      emmMsgType(msg->header.message_type));
+        emmMsgType(msg->header.message_type));
 
     switch (msg->header.message_type)
     {
-	case ATTACH_REQUEST:
-	    esm_container = &msg->attach_request.esmmessagecontainer;
-	    index += _attach_request(buffer + index, length - index,
-				     &msg->attach_request);
-	    break;
-
-	case ATTACH_ACCEPT:
-	    esm_container = &msg->attach_accept.esmmessagecontainer;
-	    index += _attach_accept(buffer + index, length - index,
-				    &msg->attach_accept);
-	    break;
-
-	case ATTACH_REJECT:
-	    esm_container = &msg->attach_reject.esmmessagecontainer;
-	    index += _attach_reject(buffer + index, length - index,
-				    &msg->attach_reject);
-	    break;
-
-	case ATTACH_COMPLETE:
-	    esm_container = &msg->attach_complete.esmmessagecontainer;
-	    index += _attach_complete(buffer + index, length - index,
-				      &msg->attach_complete);
-	    break;
-
-	case DETACH_REQUEST:
-	    index += _detach_request(buffer + index, length - index,
-				     &msg->detach_request);
-	    break;
-
-	case DETACH_ACCEPT:
-	    index += _detach_accept(buffer + index, length - index,
-				    &msg->detach_accept);
-	    break;
-
-	case IDENTITY_REQUEST:
-	    index += _identity_request(buffer + index, length - index,
-				       &msg->identity_request);
-	    break;
-
-	case IDENTITY_RESPONSE:
-	    index += _identity_response(buffer + index, length - index,
-					&msg->identity_response);
-	    break;
-
-	case AUTHENTICATION_REQUEST:
-	    index += _authentication_request(buffer + index, length - index,
-					     &msg->authentication_request);
-	    break;
-
-	case AUTHENTICATION_RESPONSE:
-	    index += _authentication_response(buffer + index, length - index,
-					      &msg->authentication_response);
-	    break;
-
-	case AUTHENTICATION_FAILURE:
-	    index += _authentication_failure(buffer + index, length - index,
-					     &msg->authentication_failure);
-	    break;
-
-	case AUTHENTICATION_REJECT:
-	    index += _authentication_reject(buffer + index, length - index,
-					    &msg->authentication_reject);
-	    break;
-
-	case SECURITY_MODE_COMMAND:
-	    index += _security_mode_command(buffer + index, length - index,
-					    &msg->security_mode_command);
-	    break;
-
-	case SECURITY_MODE_COMPLETE:
-	    index += _security_mode_complete(buffer + index, length - index,
-					     &msg->security_mode_complete);
-	    break;
-
-	case SECURITY_MODE_REJECT:
-	    index += _security_mode_reject(buffer + index, length - index,
-					   &msg->security_mode_reject);
-	    break;
-
-	case EMM_STATUS:
-	    index += _emm_status(buffer + index, length - index,
-				 &msg->emm_status);
-	    break;
-
-	default:
-	    printf("WARNING\t: %s - EMM NAS message is not valid (0x%x)\n",
-		   __FUNCTION__, msg->header.message_type);
-	    break;
+    case ATTACH_REQUEST:
+      esm_container = &msg->attach_request.esmmessagecontainer;
+      index += _attach_request(buffer + index, length - index,
+          &msg->attach_request);
+      break;
+
+    case ATTACH_ACCEPT:
+      esm_container = &msg->attach_accept.esmmessagecontainer;
+      index += _attach_accept(buffer + index, length - index,
+          &msg->attach_accept);
+      break;
+
+    case ATTACH_REJECT:
+      esm_container = &msg->attach_reject.esmmessagecontainer;
+      index += _attach_reject(buffer + index, length - index,
+          &msg->attach_reject);
+      break;
+
+    case ATTACH_COMPLETE:
+      esm_container = &msg->attach_complete.esmmessagecontainer;
+      index += _attach_complete(buffer + index, length - index,
+          &msg->attach_complete);
+      break;
+
+    case DETACH_REQUEST:
+      index += _detach_request(buffer + index, length - index,
+          &msg->detach_request);
+      break;
+
+    case DETACH_ACCEPT:
+      index += _detach_accept(buffer + index, length - index,
+          &msg->detach_accept);
+      break;
+
+    case IDENTITY_REQUEST:
+      index += _identity_request(buffer + index, length - index,
+          &msg->identity_request);
+      break;
+
+    case IDENTITY_RESPONSE:
+      index += _identity_response(buffer + index, length - index,
+          &msg->identity_response);
+      break;
+
+    case AUTHENTICATION_REQUEST:
+      index += _authentication_request(buffer + index, length - index,
+          &msg->authentication_request);
+      break;
+
+    case AUTHENTICATION_RESPONSE:
+      index += _authentication_response(buffer + index, length - index,
+          &msg->authentication_response);
+      break;
+
+    case AUTHENTICATION_FAILURE:
+      index += _authentication_failure(buffer + index, length - index,
+          &msg->authentication_failure);
+      break;
+
+    case AUTHENTICATION_REJECT:
+      index += _authentication_reject(buffer + index, length - index,
+          &msg->authentication_reject);
+      break;
+
+    case SECURITY_MODE_COMMAND:
+      index += _security_mode_command(buffer + index, length - index,
+          &msg->security_mode_command);
+      break;
+
+    case SECURITY_MODE_COMPLETE:
+      index += _security_mode_complete(buffer + index, length - index,
+          &msg->security_mode_complete);
+      break;
+
+    case SECURITY_MODE_REJECT:
+      index += _security_mode_reject(buffer + index, length - index,
+          &msg->security_mode_reject);
+      break;
+
+    case EMM_STATUS:
+      index += _emm_status(buffer + index, length - index,
+          &msg->emm_status);
+      break;
+
+    default:
+      printf("WARNING\t: %s - EMM NAS message is not valid (0x%x)\n",
+          __FUNCTION__, msg->header.message_type);
+      break;
     }
 
     index += snprintf(buffer + index, length - index, ")");
 
     /* Process ESM message container */
     if (esm_container) {
-	index += _esm_message_container(buffer + index, length - index,
-					esm_container);
+        index += _esm_message_container(buffer + index,
+            length - index,
+            esm_container);
     }
 
     return (index);
@@ -267,36 +279,42 @@ static int _nas_process_emm(char* buffer, int length, const EMM_msg* msg)
 
 /*
  *----------------------------------------------------------------------------- 
- *				Process Attach Request
+ *                              Process Attach Request
  *----------------------------------------------------------------------------- 
  */
-static int _attach_request(char* buffer, int length,
-			   const attach_request_msg* msg)
+static int
+_attach_request(
+    char* buffer,
+    int length,
+    const attach_request_msg* msg)
 {
     int index = 0;
 
     /* EPS attach type */
     index += snprintf(buffer + index, length - index, "Type = %s",
-		      attachType(&msg->epsattachtype));
+        attachType(&msg->epsattachtype));
     /* NAS key set identifier */
     index += snprintf(buffer + index, length - index, ", KSI = ");
     index += nasKeySetIdentifier(buffer + index, length - index,
-				 &msg->naskeysetidentifier);
+        &msg->naskeysetidentifier);
     /* EPS mobile identity */
     index += snprintf(buffer + index, length - index, ", ");
     index += epsIdentity(buffer + index, length - index,
-			 &msg->oldgutiorimsi);
+        &msg->oldgutiorimsi);
 
     return (index);
 }
 
 /*
  *----------------------------------------------------------------------------- 
- *				Process Attach Accept
+ *                              Process Attach Accept
  *----------------------------------------------------------------------------- 
  */
-static int _attach_accept(char* buffer, int length,
-			  const attach_accept_msg* msg)
+static int
+_attach_accept(
+    char* buffer,
+    int length,
+    const attach_accept_msg* msg)
 {
     int index = 0;
 
@@ -310,7 +328,7 @@ static int _attach_accept(char* buffer, int length,
 #endif
     /* GUTI */
     if (msg->presencemask & ATTACH_ACCEPT_GUTI_PRESENT) {
-	index += epsIdentity(buffer + index, length - index, &msg->guti);
+        index += epsIdentity(buffer + index, length - index, &msg->guti);
     }
 
     return (index);
@@ -321,14 +339,17 @@ static int _attach_accept(char* buffer, int length,
  *				Process Attach Reject
  *----------------------------------------------------------------------------- 
  */
-static int _attach_reject(char* buffer, int length,
-			  const attach_reject_msg* msg)
+static int
+_attach_reject(
+    char* buffer,
+    int length,
+    const attach_reject_msg* msg)
 {
     int index = 0;
 
     /* EMM cause code */
     index += snprintf(buffer + index, length - index, "EmmCause = %s (%d)",
-		      emmCauseCode(msg->emmcause), msg->emmcause);
+        emmCauseCode(msg->emmcause), msg->emmcause);
 
     return (index);
 }
@@ -338,8 +359,11 @@ static int _attach_reject(char* buffer, int length,
  *				Process Attach Complete
  *----------------------------------------------------------------------------- 
  */
-static int _attach_complete(char* buffer, int length,
-			    const attach_complete_msg* msg)
+static int
+_attach_complete(
+    char* buffer,
+    int length,
+    const attach_complete_msg* msg)
 {
     int index = 0;
 
@@ -351,8 +375,11 @@ static int _attach_complete(char* buffer, int length,
  *				Process Identity Request
  *----------------------------------------------------------------------------- 
  */
-static int _identity_request(char* buffer, int length,
-			     const identity_request_msg* msg)
+static int
+_identity_request(
+    char* buffer,
+    int length,
+    const identity_request_msg* msg)
 {
     int index = 0;
 
@@ -368,8 +395,11 @@ static int _identity_request(char* buffer, int length,
  *				Process Detach Request
  *----------------------------------------------------------------------------- 
  */
-static int _detach_request(char* buffer, int length,
-			   const detach_request_msg* msg)
+static int
+_detach_request(
+    char* buffer,
+    int length,
+    const detach_request_msg* msg)
 {
     int index = 0;
 
@@ -393,8 +423,11 @@ static int _detach_request(char* buffer, int length,
  *				Process Detach Accept
  *----------------------------------------------------------------------------- 
  */
-static int _detach_accept(char* buffer, int length,
-			  const detach_accept_msg* msg)
+static int
+_detach_accept(
+    char* buffer,
+    int length,
+    const detach_accept_msg* msg)
 {
     int index = 0;
 
@@ -406,8 +439,11 @@ static int _detach_accept(char* buffer, int length,
  *				Process Identity Response
  *----------------------------------------------------------------------------- 
  */
-static int _identity_response(char* buffer, int length,
-			      const identity_response_msg* msg)
+static int
+_identity_response(
+    char* buffer,
+    int length,
+    const identity_response_msg* msg)
 {
     int index = 0;
 
@@ -423,8 +459,11 @@ static int _identity_response(char* buffer, int length,
  *				Process Authentication Request
  *----------------------------------------------------------------------------- 
  */
-static int _authentication_request(char* buffer, int length,
-				   const authentication_request_msg* msg)
+static int
+_authentication_request(
+    char* buffer,
+    int length,
+    const authentication_request_msg* msg)
 {
     int index = 0;
 
@@ -449,8 +488,11 @@ static int _authentication_request(char* buffer, int length,
  *				Process Authentication Response
  *----------------------------------------------------------------------------- 
  */
-static int _authentication_response(char* buffer, int length,
-			      const authentication_response_msg* msg)
+static int
+_authentication_response(
+    char* buffer,
+    int length,
+    const authentication_response_msg* msg)
 {
     int index = 0;
 
@@ -467,8 +509,11 @@ static int _authentication_response(char* buffer, int length,
  *				Process Authentication Failure
  *----------------------------------------------------------------------------- 
  */
-static int _authentication_failure(char* buffer, int length,
-				   const authentication_failure_msg* msg)
+static int
+_authentication_failure(
+    char* buffer,
+    int length,
+    const authentication_failure_msg* msg)
 {
     int index = 0;
 
@@ -491,8 +536,11 @@ static int _authentication_failure(char* buffer, int length,
  *			    Process Authentication Reject
  *----------------------------------------------------------------------------- 
  */
-static int _authentication_reject(char* buffer, int length,
-				  const authentication_reject_msg* msg)
+static int
+_authentication_reject(
+    char* buffer,
+    int length,
+    const authentication_reject_msg* msg)
 {
     int index = 0;
 
@@ -504,23 +552,28 @@ static int _authentication_reject(char* buffer, int length,
  *			    Process Security Mode Command
  *----------------------------------------------------------------------------- 
  */
-static int _security_mode_command(char* buffer, int length,
-				  const security_mode_command_msg* msg)
+static int
+_security_mode_command(
+    char* buffer,
+    int length,
+    const security_mode_command_msg* msg)
 {
     int index = 0;
 
     /* Selected NAS ciphering algorithm */
     index += snprintf(buffer + index, length - index, "%s (%d)",
-		      nasCipheringAlgorithm(&msg->selectednassecurityalgorithms),
-		      msg->selectednassecurityalgorithms.typeofcipheringalgorithm);
+        nasCipheringAlgorithm(&msg->selectednassecurityalgorithms),
+        msg->selectednassecurityalgorithms.typeofcipheringalgorithm);
+
    /* Selected NAS integrity algorithm */
     index += snprintf(buffer + index, length - index, ", %s (%d)",
-		      nasIntegrityAlgorithm(&msg->selectednassecurityalgorithms),
-		      msg->selectednassecurityalgorithms.typeofintegrityalgorithm);
+        nasIntegrityAlgorithm(&msg->selectednassecurityalgorithms),
+        msg->selectednassecurityalgorithms.typeofintegrityalgorithm);
+
     /* NAS key set identifier */
     index += snprintf(buffer + index, length - index, ", KSI = ");
     index += nasKeySetIdentifier(buffer + index, length - index,
-				 &msg->naskeysetidentifier);
+        &msg->naskeysetidentifier);
 
     return (index);
 }
@@ -530,8 +583,11 @@ static int _security_mode_command(char* buffer, int length,
  *			    Process Security Mode Complete
  *----------------------------------------------------------------------------- 
  */
-static int _security_mode_complete(char* buffer, int length,
-				   const security_mode_complete_msg* msg)
+static int
+_security_mode_complete(
+    char* buffer,
+    int length,
+    const security_mode_complete_msg* msg)
 {
     int index = 0;
 
@@ -543,8 +599,11 @@ static int _security_mode_complete(char* buffer, int length,
  *			    Process Security Mode Reject
  *----------------------------------------------------------------------------- 
  */
-static int _security_mode_reject(char* buffer, int length,
-				 const security_mode_reject_msg* msg)
+static int
+_security_mode_reject(
+    char* buffer,
+    int length,
+    const security_mode_reject_msg* msg)
 {
     int index = 0;
 
@@ -560,8 +619,11 @@ static int _security_mode_reject(char* buffer, int length,
  *				ESM message container
  *----------------------------------------------------------------------------- 
  */
-static int _esm_message_container(char* buffer, int length,
-				  const EsmMessageContainer* msg)
+static int
+_esm_message_container(
+    char* buffer,
+    int length,
+    const EsmMessageContainer* msg)
 {
     int index = 0;
     int bytes;
@@ -595,7 +657,11 @@ static int _esm_message_container(char* buffer, int length,
  *				Process EMM Status
  *----------------------------------------------------------------------------- 
  */
-static int _emm_status(char* buffer, int length, const emm_status_msg* msg)
+static int
+_emm_status(
+    char* buffer,
+    int length,
+    const emm_status_msg* msg)
 {
     int index = 0;
 
@@ -616,95 +682,99 @@ static int _emm_status(char* buffer, int length, const emm_status_msg* msg)
  *		    Process EPS Session MAnagement NAS message
  *----------------------------------------------------------------------------- 
  */
-static int _nas_process_esm(char* buffer, int length, const ESM_msg* msg)
+static int
+_nas_process_esm(
+    char* buffer,
+    int length,
+    const ESM_msg* msg)
 {
     int index = 0;
 
     printf("INFO\t: Process %s\n", esmMsgType(msg->header.message_type));
     index += snprintf(buffer + index, length - index, "%s (pti=%d, ebi=%d",
-		      esmMsgType(msg->header.message_type),
-		      msg->header.procedure_transaction_identity,
-		      msg->header.eps_bearer_identity);
+        esmMsgType(msg->header.message_type),
+        msg->header.procedure_transaction_identity,
+        msg->header.eps_bearer_identity);
 
     switch (msg->header.message_type)
     {
-	case PDN_CONNECTIVITY_REQUEST:
-	    index += _pdn_connectivity_request(buffer + index, length - index,
-					       &msg->pdn_connectivity_request);
-	    break;
-
-	case PDN_CONNECTIVITY_REJECT:
-	    index += _pdn_connectivity_reject(buffer + index, length - index,
-					      &msg->pdn_connectivity_reject);
-	    break;
-
-	case PDN_DISCONNECT_REQUEST:
-	    index += _pdn_disconnect_request(buffer + index, length - index,
-					       &msg->pdn_disconnect_request);
-	    break;
-
-	case PDN_DISCONNECT_REJECT:
-	    index += _pdn_disconnect_reject(buffer + index, length - index,
-					    &msg->pdn_disconnect_reject);
-	    break;
-
-	case ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST:
-	    index += _activate_default_eps_bearer_context_request(
-			buffer + index, length - index,
-			&msg->activate_default_eps_bearer_context_request);
-	    break;
-
-	case ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT:
-	    index += _activate_default_eps_bearer_context_accept(
-			buffer + index, length - index,
-			&msg->activate_default_eps_bearer_context_accept);
-	    break;
-
-	case ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT:
-	    index += _activate_default_eps_bearer_context_reject(
-			buffer + index, length - index,
-			&msg->activate_default_eps_bearer_context_reject);
-	    break;
-
-	case ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST:
-	    index += _activate_dedicated_eps_bearer_context_request(
-			buffer + index, length - index,
-			&msg->activate_dedicated_eps_bearer_context_request);
-	    break;
-
-	case ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT:
-	    index += _activate_dedicated_eps_bearer_context_accept(
-			buffer + index, length - index,
-			&msg->activate_dedicated_eps_bearer_context_accept);
-	    break;
-
-	case ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT:
-	    index += _activate_dedicated_eps_bearer_context_reject(
-			buffer + index, length - index,
-			&msg->activate_dedicated_eps_bearer_context_reject);
-	    break;
-
-	case DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST:
-	    index += _deactivate_eps_bearer_context_request(buffer + index,
-							    length - index,
-				&msg->deactivate_eps_bearer_context_request);
-	    break;
-
-	case DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT:
-	    index += _deactivate_eps_bearer_context_accept(buffer + index,
-							   length - index,
-				&msg->deactivate_eps_bearer_context_accept);
-	    break;
-
-	case ESM_STATUS:
-	    index += _esm_status(buffer + index, length - index,
-				 &msg->esm_status);
-	    break;
-
-	default:
-	    printf("WARNING\t: %s - ESM NAS message is not valid (0x%x)\n",
-		   __FUNCTION__, msg->header.message_type);
-	    break;
+    case PDN_CONNECTIVITY_REQUEST:
+      index += _pdn_connectivity_request(buffer + index, length - index,
+          &msg->pdn_connectivity_request);
+      break;
+
+    case PDN_CONNECTIVITY_REJECT:
+      index += _pdn_connectivity_reject(buffer + index, length - index,
+          &msg->pdn_connectivity_reject);
+      break;
+
+    case PDN_DISCONNECT_REQUEST:
+      index += _pdn_disconnect_request(buffer + index, length - index,
+          &msg->pdn_disconnect_request);
+      break;
+
+    case PDN_DISCONNECT_REJECT:
+      index += _pdn_disconnect_reject(buffer + index, length - index,
+          &msg->pdn_disconnect_reject);
+      break;
+
+    case ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REQUEST:
+      index += _activate_default_eps_bearer_context_request(
+          buffer + index, length - index,
+          &msg->activate_default_eps_bearer_context_request);
+      break;
+
+    case ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_ACCEPT:
+      index += _activate_default_eps_bearer_context_accept(
+          buffer + index, length - index,
+          &msg->activate_default_eps_bearer_context_accept);
+      break;
+
+    case ACTIVATE_DEFAULT_EPS_BEARER_CONTEXT_REJECT:
+      index += _activate_default_eps_bearer_context_reject(
+          buffer + index, length - index,
+          &msg->activate_default_eps_bearer_context_reject);
+      break;
+
+    case ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REQUEST:
+      index += _activate_dedicated_eps_bearer_context_request(
+          buffer + index, length - index,
+          &msg->activate_dedicated_eps_bearer_context_request);
+      break;
+
+    case ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_ACCEPT:
+      index += _activate_dedicated_eps_bearer_context_accept(
+          buffer + index, length - index,
+          &msg->activate_dedicated_eps_bearer_context_accept);
+      break;
+
+    case ACTIVATE_DEDICATED_EPS_BEARER_CONTEXT_REJECT:
+      index += _activate_dedicated_eps_bearer_context_reject(
+          buffer + index, length - index,
+          &msg->activate_dedicated_eps_bearer_context_reject);
+      break;
+
+    case DEACTIVATE_EPS_BEARER_CONTEXT_REQUEST:
+      index += _deactivate_eps_bearer_context_request(buffer + index,
+          length - index,
+          &msg->deactivate_eps_bearer_context_request);
+      break;
+
+    case DEACTIVATE_EPS_BEARER_CONTEXT_ACCEPT:
+      index += _deactivate_eps_bearer_context_accept(buffer + index,
+          length - index,
+          &msg->deactivate_eps_bearer_context_accept);
+      break;
+
+    case ESM_STATUS:
+      index += _esm_status(buffer + index, length - index,
+          &msg->esm_status);
+      break;
+
+    default:
+      printf("WARNING\t: %s - ESM NAS message is not valid (0x%x)\n",
+          __FUNCTION__, msg->header.message_type);
+      break;
     }
 
     index += snprintf(buffer + index, length - index, ")");
@@ -714,24 +784,27 @@ static int _nas_process_esm(char* buffer, int length, const ESM_msg* msg)
 
 /*
  *----------------------------------------------------------------------------- 
- *			    Process PDN Connectivity Request
+ *                          Process PDN Connectivity Request
  *----------------------------------------------------------------------------- 
  */
-static int _pdn_connectivity_request(char* buffer, int length,
-				     const pdn_connectivity_request_msg* msg)
+static int
+_pdn_connectivity_request(
+    char* buffer,
+    int length,
+    const pdn_connectivity_request_msg* msg)
 {
     int index = 0;
 
     /* PDN request type and PDN type */
     index += snprintf(buffer + index, length - index,
-		      ", RequestType = %s, PdnType = %s",
-		      requestType(&msg->requesttype),
-		      pdnType(&msg->pdntype));
+        ", RequestType = %s, PdnType = %s",
+        requestType(&msg->requesttype),
+        pdnType(&msg->pdntype));
     /* Access Point Name */
     if (msg->presencemask & PDN_CONNECTIVITY_REQUEST_ACCESS_POINT_NAME_PRESENT)
     {
-	index += snprintf(buffer + index, length - index, ", APN = %s",
-			(char*)msg->accesspointname.accesspointnamevalue.value);
+        index += snprintf(buffer + index, length - index, ", APN = %s",
+            (char*)msg->accesspointname.accesspointnamevalue.value);
     }
 
     return (index);
@@ -739,17 +812,20 @@ static int _pdn_connectivity_request(char* buffer, int length,
 
 /*
  *----------------------------------------------------------------------------- 
- *			    Process PDN Connectivity Reject
+ *                          Process PDN Connectivity Reject
  *----------------------------------------------------------------------------- 
  */
-static int _pdn_connectivity_reject(char* buffer, int length,
-				    const pdn_connectivity_reject_msg* msg)
+static int
+_pdn_connectivity_reject(
+    char* buffer,
+    int length,
+    const pdn_connectivity_reject_msg* msg)
 {
     int index = 0;
 
     /* ESM cause code */
     index += snprintf(buffer + index, length - index, ", EsmCause = %s (%d)",
-		      esmCauseCode(msg->esmcause), msg->esmcause);
+        esmCauseCode(msg->esmcause), msg->esmcause);
 
     return (index);
 }
@@ -759,48 +835,57 @@ static int _pdn_connectivity_reject(char* buffer, int length,
  *			    Process PDN Disconnect Request
  *----------------------------------------------------------------------------- 
  */
-static int _pdn_disconnect_request(char* buffer, int length,
-				   const pdn_disconnect_request_msg* msg)
+static int
+_pdn_disconnect_request(
+    char* buffer,
+    int length,
+    const pdn_disconnect_request_msg* msg)
 {
     int index = 0;
 
     /* Linked EPS bearer identity */
     index += snprintf(buffer + index, length - index, ", Linked EBI = %d",
-		      msg->linkedepsbeareridentity);
+        msg->linkedepsbeareridentity);
 
     return (index);
 }
 
 /*
  *----------------------------------------------------------------------------- 
- *			    Process PDN Disconnect Reject
+ *                          Process PDN Disconnect Reject
  *----------------------------------------------------------------------------- 
  */
-static int _pdn_disconnect_reject(char* buffer, int length,
-				  const pdn_disconnect_reject_msg* msg)
+static int
+_pdn_disconnect_reject(
+    char* buffer,
+    int length,
+    const pdn_disconnect_reject_msg* msg)
 {
     int index = 0;
 
     /* ESM cause code */
     index += snprintf(buffer + index, length - index, ", EsmCause = %s (%d)",
-		      esmCauseCode(msg->esmcause), msg->esmcause);
+        esmCauseCode(msg->esmcause), msg->esmcause);
 
     return (index);
 }
 
 /*
  *----------------------------------------------------------------------------- 
- *		Process Activate Default EPS Bearer Context Request
+ *              Process Activate Default EPS Bearer Context Request
  *----------------------------------------------------------------------------- 
  */
-static int _activate_default_eps_bearer_context_request(char* buffer, int length,
-		const activate_default_eps_bearer_context_request_msg* msg)
+static int
+_activate_default_eps_bearer_context_request(
+    char* buffer,
+    int length,
+    const activate_default_eps_bearer_context_request_msg* msg)
 {
     int index = 0;
 
     /* Access Point Name */
     index += snprintf(buffer + index, length - index, ", APN = %s",
-    		      (char*)msg->accesspointname.accesspointnamevalue.value);
+        (char*)msg->accesspointname.accesspointnamevalue.value);
 
     /* PDN address */
     index += snprintf(buffer + index, length - index, ", PDN addr = ");
@@ -814,8 +899,11 @@ static int _activate_default_eps_bearer_context_request(char* buffer, int length
  *		Process Activate Default EPS Bearer Context Accept
  *----------------------------------------------------------------------------- 
  */
-static int _activate_default_eps_bearer_context_accept(char* buffer, int length,
-		const activate_default_eps_bearer_context_accept_msg* msg)
+static int
+_activate_default_eps_bearer_context_accept(
+    char* buffer,
+    int length,
+    const activate_default_eps_bearer_context_accept_msg* msg)
 {
     int index = 0;
 
@@ -827,14 +915,17 @@ static int _activate_default_eps_bearer_context_accept(char* buffer, int length,
  *		Process Activate Default EPS Bearer Context Reject
  *----------------------------------------------------------------------------- 
  */
-static int _activate_default_eps_bearer_context_reject(char* buffer, int length,
-		const activate_default_eps_bearer_context_reject_msg* msg)
+static int
+_activate_default_eps_bearer_context_reject(
+    char* buffer,
+    int length,
+    const activate_default_eps_bearer_context_reject_msg* msg)
 {
     int index = 0;
 
     /* ESM cause code */
     index += snprintf(buffer + index, length - index, ", EsmCause = %s (%d)",
-		      esmCauseCode(msg->esmcause), msg->esmcause);
+        esmCauseCode(msg->esmcause), msg->esmcause);
 
     return (index);
 }
@@ -844,9 +935,11 @@ static int _activate_default_eps_bearer_context_reject(char* buffer, int length,
  *		Process Activate Dedicated EPS Bearer Context Request
  *----------------------------------------------------------------------------- 
  */
-static int _activate_dedicated_eps_bearer_context_request(
-		char* buffer, int length,
-		const activate_dedicated_eps_bearer_context_request_msg* msg)
+static int
+_activate_dedicated_eps_bearer_context_request(
+    char* buffer,
+    int length,
+    const activate_dedicated_eps_bearer_context_request_msg* msg)
 {
     int index = 0;
 
@@ -862,9 +955,11 @@ static int _activate_dedicated_eps_bearer_context_request(
  *		Process Activate Dedicated EPS Bearer Context Accept
  *----------------------------------------------------------------------------- 
  */
-static int _activate_dedicated_eps_bearer_context_accept(
-		char* buffer, int length,
-		const activate_dedicated_eps_bearer_context_accept_msg* msg)
+static int
+_activate_dedicated_eps_bearer_context_accept(
+    char* buffer,
+    int length,
+    const activate_dedicated_eps_bearer_context_accept_msg* msg)
 {
     int index = 0;
 
@@ -876,15 +971,17 @@ static int _activate_dedicated_eps_bearer_context_accept(
  *		Process Activate Dedicated EPS Bearer Context Reject
  *----------------------------------------------------------------------------- 
  */
-static int _activate_dedicated_eps_bearer_context_reject(
-		char* buffer, int length,
-		const activate_dedicated_eps_bearer_context_reject_msg* msg)
+static int
+_activate_dedicated_eps_bearer_context_reject(
+    char* buffer,
+    int length,
+    const activate_dedicated_eps_bearer_context_reject_msg* msg)
 {
     int index = 0;
 
     /* ESM cause code */
     index += snprintf(buffer + index, length - index, ", EsmCause = %s (%d)",
-		      esmCauseCode(msg->esmcause), msg->esmcause);
+        esmCauseCode(msg->esmcause), msg->esmcause);
 
     return (index);
 }
@@ -894,14 +991,16 @@ static int _activate_dedicated_eps_bearer_context_reject(
  *		Process Deactivate EPS Bearer Context Request
  *----------------------------------------------------------------------------- 
  */
-static int _deactivate_eps_bearer_context_request(char* buffer, int length,
-		const deactivate_eps_bearer_context_request_msg* msg)
+static int _deactivate_eps_bearer_context_request(
+    char* buffer,
+    int length,
+    const deactivate_eps_bearer_context_request_msg* msg)
 {
     int index = 0;
 
     /* ESM cause code */
     index += snprintf(buffer + index, length - index, ", EsmCause = %s (%d)",
-		      esmCauseCode(msg->esmcause), msg->esmcause);
+        esmCauseCode(msg->esmcause), msg->esmcause);
 
     return (index);
 }
@@ -911,8 +1010,11 @@ static int _deactivate_eps_bearer_context_request(char* buffer, int length,
  *		Process Deactivate EPS Bearer Context Accept
  *----------------------------------------------------------------------------- 
  */
-static int _deactivate_eps_bearer_context_accept(char* buffer, int length,
-		const deactivate_eps_bearer_context_accept_msg* msg)
+static int
+_deactivate_eps_bearer_context_accept(
+    char* buffer,
+    int length,
+    const deactivate_eps_bearer_context_accept_msg* msg)
 {
     int index = 0;
 
@@ -924,13 +1026,17 @@ static int _deactivate_eps_bearer_context_accept(char* buffer, int length,
  *				Process ESM Status
  *----------------------------------------------------------------------------- 
  */
-static int _esm_status(char* buffer, int length, const esm_status_msg* msg)
+static int
+_esm_status(
+    char* buffer,
+    int length,
+    const esm_status_msg* msg)
 {
     int index = 0;
 
     /* ESM cause code */
     index += snprintf(buffer + index, length - index, ", EsmCause = %s (%d)",
-		      esmCauseCode(msg->esmcause), msg->esmcause);
+        esmCauseCode(msg->esmcause), msg->esmcause);
 
     return (index);
 }
diff --git a/openair-cn/NAS/Makefile.am b/openair-cn/NAS/Makefile.am
index 91ddf3358c..302e96edc2 100644
--- a/openair-cn/NAS/Makefile.am
+++ b/openair-cn/NAS/Makefile.am
@@ -8,6 +8,7 @@ AM_CFLAGS =											\
 	-DEPC_BUILD										\
 	-DENABLE_ITTI									\
 	-I$(top_srcdir)/COMMON							\
+	-I$(top_srcdir)/SECU							\
 	-I$(top_srcdir)/INTERTASK_INTERFACE				\
 	-I$(top_srcdir)/NAS/EURECOM-NAS/src/api/user	\
 	-I$(top_srcdir)/NAS/EURECOM-NAS/src/api/mme		\
diff --git a/openair-cn/NAS/Makefile.inc b/openair-cn/NAS/Makefile.inc
index 8e66de5609..3222655e1b 100644
--- a/openair-cn/NAS/Makefile.inc
+++ b/openair-cn/NAS/Makefile.inc
@@ -1,7 +1,7 @@
 libnas_api_SRCS =								\
     EURECOM-NAS/src/api/mme/mme_api.c			\
     EURECOM-NAS/src/api/mme/mme_api.h			\
-    EURECOM-NAS/src/api/network/nas_message.c	\
+    EURECOM-NAS/src/api/network/nas_message.c   \
     EURECOM-NAS/src/api/network/nas_message.h
 
 libnas_emm_SRCS =								\
diff --git a/openair-cn/README b/openair-cn/README
index 08c7575eb9..e3205fb798 100644
--- a/openair-cn/README
+++ b/openair-cn/README
@@ -11,7 +11,7 @@ MME + P-GW + S-GW implementation of 3GPP standard.
 Controle plane:
 
               eNB                                    MME                                     HSS
- 
+
                                        |----------------------------|
                                        |    MME Application layer   |
                                        |----------------------------|
@@ -88,7 +88,7 @@ Current options supported for configure:
 code build switch: UPDATE_RELEASE_9 and UPDATE_RELEASE_10
 NOTE: Release 10 is enabled by default
 --enable-standalone-epc: all-in-one package, MME, S-GW and P-GW are compiled in a single
-executable and S11 interface is not used; messages are exchanged internally, 
+executable and S11 interface is not used; messages are exchanged internally,
 linking MME applicative layer to S+P-GW applicative layer
 
 How to run EPC environnement ?
diff --git a/openair-cn/S1AP/s1ap_mme_nas_procedures.c b/openair-cn/S1AP/s1ap_mme_nas_procedures.c
index 2bc27ee822..273c4467d1 100644
--- a/openair-cn/S1AP/s1ap_mme_nas_procedures.c
+++ b/openair-cn/S1AP/s1ap_mme_nas_procedures.c
@@ -653,12 +653,18 @@ void s1ap_handle_conn_est_cnf(const mme_app_connection_establishment_cnf_t * con
     initialContextSetupRequest_p->ueSecurityCapabilities.integrityProtectionAlgorithms.bits_unused
         = 0;
 
-//    initialContextSetupRequest_p->securityKey.buf  = initial_p->keNB; /* 256 bits length */
-    uint8_t keNB[32];
-    memset(keNB, 0, sizeof(keNB));
+    if (conn_est_cnf_pP->keNB) {
+        initialContextSetupRequest_p->securityKey.buf = malloc(32);
+        memcpy(initialContextSetupRequest_p->securityKey.buf,
+            conn_est_cnf_pP->keNB,
+            32);
 
-    initialContextSetupRequest_p->securityKey.buf = keNB;
-    initialContextSetupRequest_p->securityKey.size = 32;
+        initialContextSetupRequest_p->securityKey.size = 32;
+    } else {
+        S1AP_DEBUG("No keNB\n");
+        initialContextSetupRequest_p->securityKey.buf = NULL;
+        initialContextSetupRequest_p->securityKey.size = 0;
+    }
     initialContextSetupRequest_p->securityKey.bits_unused = 0;
 
     if (s1ap_mme_encode_pdu(&message, &buffer_p, &length) < 0) {
diff --git a/openair-cn/SECU/nas_stream_eia2.c b/openair-cn/SECU/nas_stream_eia2.c
index 5942498813..517d388098 100644
--- a/openair-cn/SECU/nas_stream_eia2.c
+++ b/openair-cn/SECU/nas_stream_eia2.c
@@ -9,10 +9,15 @@
 #include <openssl/cmac.h>
 #include <openssl/evp.h>
 
+// test
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/bio.h>
+
 #include "assertions.h"
 #include "conversions.h"
 
-// #define SECU_DEBUG
+#define SECU_DEBUG
 
 /*!
  * @brief Create integrity cmac t for a given message.
@@ -21,19 +26,19 @@
  */
 int nas_stream_encrypt_eia2(nas_stream_cipher_t *stream_cipher, uint8_t out[4])
 {
-    uint8_t  *m;
-    uint32_t local_count;
-    size_t size = 4;
-
-    uint8_t  data[16];
-
-    CMAC_CTX *cmac_ctx;
-
-    uint32_t zero_bit = 0;
-    uint32_t m_length;
+    uint8_t          *m            = NULL;
+    uint32_t          local_count;
+    size_t            size         = 4;
+    uint8_t           data[16];
+    CMAC_CTX         *cmac_ctx     = NULL;
+    const EVP_CIPHER *cipher       = EVP_aes_128_cbc();
+    uint32_t          zero_bit     = 0;
+    uint32_t          m_length;
+    int               ret;
 
     DevAssert(stream_cipher != NULL);
     DevAssert(stream_cipher->key != NULL);
+    DevAssert(stream_cipher->key_length > 0);
     DevAssert(out != NULL);
 
     memset(data, 0, 16);
@@ -59,24 +64,36 @@ int nas_stream_encrypt_eia2(nas_stream_cipher_t *stream_cipher, uint8_t out[4])
         printf("Byte length: %u, Zero bits: %u\nm: ", m_length + 8, zero_bit);
         for (i = 0; i < m_length + 8; i++)
             printf("%02x", m[i]);
+        printf("\nKey:");
+        for (i = 0; i < stream_cipher->key_length; i++)
+            printf("%02x", stream_cipher->key[i]);
+        printf("\nMessage:");
+        for (i = 0; i < m_length; i++)
+            printf("%02x", stream_cipher->message[i]);
         printf("\n");
     }
 #endif
 
     cmac_ctx = CMAC_CTX_new();
-
-    CMAC_Init(cmac_ctx, stream_cipher->key, stream_cipher->key_length, EVP_aes_128_cbc(), NULL);
-    CMAC_Update(cmac_ctx, m, m_length + 8);
-
+    ret = CMAC_Init(cmac_ctx, stream_cipher->key, stream_cipher->key_length, cipher, NULL);
+#if defined(SECU_DEBUG)
+    printf("CMAC_Init returned %d\n", ret);
+#endif
+    ret = CMAC_Update(cmac_ctx, m, m_length + 8);
+#if defined(SECU_DEBUG)
+    printf("CMAC_Update returned %d\n", ret);
+#endif
     CMAC_Final(cmac_ctx, data, &size);
-
+#if defined(SECU_DEBUG)
+    printf("CMAC_Final returned %d, size = %u\n", ret, size);
+#endif
     CMAC_CTX_free(cmac_ctx);
 
 #if defined(SECU_DEBUG)
     {
         int i;
         printf("out: ");
-        for (i = 0; i < 16; i++)
+        for (i = 0; i < size; i++)
             printf("%02x", data[i]);
         printf("\n");
     }
diff --git a/openair-cn/SECU/secu_defs.h b/openair-cn/SECU/secu_defs.h
index 8987f55edd..6be6db2c8c 100644
--- a/openair-cn/SECU/secu_defs.h
+++ b/openair-cn/SECU/secu_defs.h
@@ -7,6 +7,13 @@
 #define EIA1_128_ALG_ID 0x01
 #define EIA2_128_ALG_ID 0x02
 
+#define EEA0_ALG_ID     0x00
+#define EEA1_128_ALG_ID 0x01
+#define EEA2_128_ALG_ID 0x02
+
+#define SECU_DIRECTION_UPLINK   0
+#define SECU_DIRECTION_DOWNLINK 1
+
 inline
 void kdf(const uint8_t *s, const uint32_t s_length, const uint8_t *key,
          const uint32_t key_length, uint8_t **out, uint32_t out_length);
-- 
2.26.2