From 2817ad4d29ec4b07723c71715b5f118ccc479bff Mon Sep 17 00:00:00 2001
From: Cedric Roux <cedric.roux@eurecom.fr>
Date: Thu, 5 Dec 2013 13:14:43 +0000
Subject: [PATCH] - Added upper layer support for NAS MME 	* Correctly
 fetch user authentication vector from HSS 	* Trigger authentication
 procedure based on the returned vector - Removed unused security types

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4608 818b1a75-f10b-46b9-bf7c-635c3b92a50f
---
 openair-cn/COMMON/common_types.h              |   8 +-
 openair-cn/COMMON/messages_types.h            |   2 +
 openair-cn/COMMON/nas_messages_def.h          |   8 +-
 openair-cn/COMMON/nas_messages_types.h        |  34 ++++-
 openair-cn/COMMON/security_types.h            |  65 +--------
 openair-cn/MME_APP/Makefile.am                |   1 +
 openair-cn/MME_APP/mme_app_authentication.c   | 137 ++++++++++++------
 openair-cn/MME_APP/mme_app_context.c          |   6 +-
 openair-cn/MME_APP/mme_app_defs.h             |   5 +-
 openair-cn/MME_APP/mme_app_main.c             |   8 +-
 openair-cn/MME_APP/mme_app_ue_context.h       |  14 +-
 openair-cn/MME_APP/s6a_2_nas_cause.c          |  25 +---
 openair-cn/Makefile.am                        |   2 +-
 openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c   |  72 +++++----
 openair-cn/NAS/EURECOM-NAS/src/emm/emm_proc.h |   2 +
 .../NAS/EURECOM-NAS/src/emm/sap/emm_as.c      |  31 ++--
 .../NAS/EURECOM-NAS/src/emm/sap/emm_cn.c      | 134 +++++++++++++++++
 .../NAS/EURECOM-NAS/src/emm/sap/emm_cn.h      |  28 ++++
 .../NAS/EURECOM-NAS/src/emm/sap/emm_cnDef.h   |  48 ++++++
 .../NAS/EURECOM-NAS/src/emm/sap/emm_sap.c     |  16 +-
 .../NAS/EURECOM-NAS/src/emm/sap/emm_sap.h     |  33 +++--
 .../NAS/EURECOM-NAS/src/include/securityDef.h |  17 ++-
 openair-cn/NAS/EURECOM-NAS/src/nas_proc.c     |  36 ++++-
 openair-cn/NAS/EURECOM-NAS/src/nas_proc.h     |  12 ++
 .../NAS/EURECOM-NAS/src/util/OctetString.h    |   4 +-
 openair-cn/NAS/Makefile.inc                   |   3 +-
 openair-cn/NAS/nas_itti_messaging.c           |   4 +-
 openair-cn/NAS/nas_itti_messaging.h           |  49 ++++++-
 openair-cn/NAS/nas_main.c                     |  14 +-
 openair-cn/S6A/s6a_auth_info.c                |  26 ++--
 30 files changed, 608 insertions(+), 236 deletions(-)
 create mode 100644 openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.c
 create mode 100644 openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.h
 create mode 100644 openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cnDef.h

diff --git a/openair-cn/COMMON/common_types.h b/openair-cn/COMMON/common_types.h
index 74af62ef085..3631ce6b588 100644
--- a/openair-cn/COMMON/common_types.h
+++ b/openair-cn/COMMON/common_types.h
@@ -32,6 +32,8 @@
 
 #include "commonDef.h"
 
+#include "security_types.h"
+
 #include "queue.h"
 
 #ifndef COMMON_TYPES_H_
@@ -215,9 +217,9 @@ typedef struct {
     rau_tau_timer_t       rau_tau_timer;
 } subscription_data_t;
 
-typedef struct {
-    uint8_t nb_of_vectors;
-    STAILQ_HEAD(e_utran_vector_list, eutran_vector_s) e_utran_vectors;
+typedef struct authentication_info_s {
+    uint8_t         nb_of_vectors;
+    eutran_vector_t eutran_vector;
 } authentication_info_t;
 
 typedef enum {
diff --git a/openair-cn/COMMON/messages_types.h b/openair-cn/COMMON/messages_types.h
index fc5048c4510..e73fc627931 100644
--- a/openair-cn/COMMON/messages_types.h
+++ b/openair-cn/COMMON/messages_types.h
@@ -10,6 +10,8 @@
 
 #include "timer_messages_types.h"
 
+#include "security_types.h"
+
 #include "gtpv1_u_messages_types.h"
 #include "ip_forward_messages_types.h"
 #include "mme_app_messages_types.h"
diff --git a/openair-cn/COMMON/nas_messages_def.h b/openair-cn/COMMON/nas_messages_def.h
index a7a1e3154e0..d01c51d648e 100644
--- a/openair-cn/COMMON/nas_messages_def.h
+++ b/openair-cn/COMMON/nas_messages_def.h
@@ -13,14 +13,16 @@ MESSAGE_DEF(NAS_RAB_ESTABLISHMENT_RESP,       MESSAGE_PRIORITY_MED, nas_rab_est_
 MESSAGE_DEF(NAS_RAB_RELEASE_REQ,              MESSAGE_PRIORITY_MED, nas_rab_rel_req_t,   nas_rab_rel_req)
 
 /* NAS layer -> MME app messages */
-MESSAGE_DEF(NAS_AUTHENTICATION_REQ,           MESSAGE_PRIORITY_MED, nas_auth_req_t,       nas_auth_req)
 MESSAGE_DEF(NAS_AUTHENTICATION_PARAM_REQ,     MESSAGE_PRIORITY_MED, nas_auth_param_req_t, nas_auth_param_req)
 
 /* MME app -> NAS layer messages */
-MESSAGE_DEF(NAS_BEARER_PARAM,                 MESSAGE_PRIORITY_MED, nas_bearer_param_t,  nas_bearer_param)
-MESSAGE_DEF(NAS_AUTHENTICATION_RESP,          MESSAGE_PRIORITY_MED, nas_auth_resp_t,     nas_auth_resp)
+MESSAGE_DEF(NAS_BEARER_PARAM,                 MESSAGE_PRIORITY_MED, nas_bearer_param_t,    nas_bearer_param)
+MESSAGE_DEF(NAS_AUTHENTICATION_PARAM_RSP,     MESSAGE_PRIORITY_MED, nas_auth_param_rsp_t,  nas_auth_param_rsp)
+MESSAGE_DEF(NAS_AUTHENTICATION_PARAM_FAIL,    MESSAGE_PRIORITY_MED, nas_auth_param_fail_t, nas_auth_param_fail)
 
 #if defined(DISABLE_USE_NAS)
 MESSAGE_DEF(NAS_ATTACH_REQ,                   MESSAGE_PRIORITY_MED, nas_attach_req_t,    nas_attach_req)
 MESSAGE_DEF(NAS_ATTACH_ACCEPT,                MESSAGE_PRIORITY_MED, nas_attach_accept_t, nas_attach_accept)
+MESSAGE_DEF(NAS_AUTHENTICATION_RESP,          MESSAGE_PRIORITY_MED, nas_auth_resp_t,     nas_auth_resp)
+MESSAGE_DEF(NAS_AUTHENTICATION_REQ,           MESSAGE_PRIORITY_MED, nas_auth_req_t,      nas_auth_req)
 #endif
\ No newline at end of file
diff --git a/openair-cn/COMMON/nas_messages_types.h b/openair-cn/COMMON/nas_messages_types.h
index 7031eec40c1..a3a0fa1349a 100644
--- a/openair-cn/COMMON/nas_messages_types.h
+++ b/openair-cn/COMMON/nas_messages_types.h
@@ -11,6 +11,8 @@
 #define NAS_BEARER_PARAM(mSGpTR)                (mSGpTR)->ittiMsg.nas_bearer_param
 #define NAS_AUTHENTICATION_REQ(mSGpTR)          (mSGpTR)->ittiMsg.nas_auth_req
 #define NAS_AUTHENTICATION_PARAM_REQ(mSGpTR)    (mSGpTR)->ittiMsg.nas_auth_param_req
+#define NAS_AUTHENTICATION_PARAM_RSP(mSGpTR)    (mSGpTR)->ittiMsg.nas_auth_param_rsp
+#define NAS_AUTHENTICATION_PARAM_FAIL(mSGpTR)   (mSGpTR)->ittiMsg.nas_auth_param_fail
 
 typedef struct {
     
@@ -25,6 +27,8 @@ typedef struct {
     s1ap_initial_ue_message_t transparent;
 } nas_conn_est_ind_t;
 
+typedef nas_establish_rsp_t nas_conn_est_rej_t;
+
 typedef struct nas_conn_est_cnf_s {
     uint32_t ue_id;
 
@@ -107,12 +111,36 @@ typedef struct {
 } nas_auth_resp_t;
 
 typedef struct nas_auth_param_req_s {
-    uint8_t imsi_length;
-    char    imsi[15];
+    /* UE identifier */
+    uint32_t ue_id;
+
+    /* Imsi of the UE (In case of initial request) */
+    char     imsi[16];
+    uint8_t  imsi_length;
 
-    uint8_t initial_req:1;
+    /* Indicates whether the procedure corresponds to a new connection or not */
+    uint8_t  initial_req:1;
 } nas_auth_param_req_t;
 
+typedef struct nas_auth_param_rsp_s {
+    /* UE identifier */
+    uint32_t ue_id;
+
+    /* For future use: nb of vectors provided */
+    uint8_t nb_vectors;
+
+    /* Consider only one E-UTRAN vector for the moment... */
+    eutran_vector_t vector;
+} nas_auth_param_rsp_t;
+
+typedef struct nas_auth_param_fail_s {
+    /* UE identifier */
+    uint32_t    ue_id;
+
+    /* S6A mapped to NAS cause */
+    nas_cause_t cause;
+} nas_auth_param_fail_t;
+
 typedef struct nas_attach_accept_s {
     
 } nas_attach_accept_t;
diff --git a/openair-cn/COMMON/security_types.h b/openair-cn/COMMON/security_types.h
index 9affe8ad1ce..1806a39efd3 100644
--- a/openair-cn/COMMON/security_types.h
+++ b/openair-cn/COMMON/security_types.h
@@ -35,65 +35,6 @@
     sscanf(sTRING, "%" SCNu64, cONTAINER)
 */
 
-/* GCC supports 128 bits integers on certain architectures */
-#if defined(ENABLE_GMP_TYPES)
-/* Use gmplib in case GCC doesn't support 128 bits integers natively */
-typedef mpz_t rand_t;
-typedef mpz_t auth_key_t;
-typedef mpz_t auth_res_t;
-typedef mpz_t kasme_t;
-typedef mpz_t autn_t;
-
-/* RES amd XRES can have a variable length of 4-16 octets */
-typedef struct {
-    ssize_t    size;
-    auth_res_t data;
-} res_t;
-
-/* Converts a string to 128 bits gmplib integer holder */
-# define STRING_TO_XBITS(sTRING, lENGTH, cONTAINER, rET)        \
-do {                                                            \
-    char temp[129];                                             \
-    if (lENGTH > 64) {                                          \
-        rET = -1;                                               \
-    } else {                                                    \
-        hexa_to_ascii(sTRING, temp, lENGTH);                    \
-        temp[2 * lENGTH] = '\0';                                \
-        rET = mpz_init_set_str (cONTAINER, temp, 16);           \
-    }                                                           \
-} while(0)
-
-# define STRING_TO_128BITS(sTRING, cONTAINER, rET)  \
-STRING_TO_XBITS(sTRING, 16, cONTAINER, rET)
-
-# define STRING_TO_256BITS(sTRING, cONTAINER, rET)  \
-STRING_TO_XBITS(sTRING, 32, cONTAINER, rET)
-
-# define STRING_TO_RAND      STRING_TO_128BITS
-# define STRING_TO_AUTH_KEY  STRING_TO_128BITS
-# define STRING_TO_AUTH_RES  STRING_TO_128BITS
-# define STRING_TO_AUTN      STRING_TO_128BITS
-# define STRING_TO_KASME     STRING_TO_256BITS
-# define STRING_TO_XRES(sTRING, lENGTH, cONTAINER, rET)             \
-do {                                                                \
-    STRING_TO_XBITS(sTRING, lENGTH, (cONTAINER)->data, rET);        \
-    if (rET != -1)                                                  \
-        (cONTAINER)->size = mpz_sizeinbase((cONTAINER)->data, 16);  \
-} while(0)
-
-/* Holds an E-UTRAN authentication vector */
-typedef struct eutran_vector_s {
-    rand_t  rand;
-    res_t   xres;
-    autn_t  autn;
-    kasme_t kasme;
-
-    /* one UE can have multiple vectors so use STAILQ lists for easy management */
-    STAILQ_ENTRY(eutran_vector_s) entries;
-} eutran_vector_t;
-
-#else /* defined(ENABLE_GMP_TYPES) */
-
 /* Converts a string to 128 bits gmplib integer holder */
 # define STRING_TO_XBITS(sTRING, lENGTH, cONTAINER, rET)        \
 do {                                                            \
@@ -121,7 +62,7 @@ do {                                                            \
 
 /* RES amd XRES can have a variable length of 4-16 octets */
 typedef struct {
-    ssize_t size;
+    uint8_t size;
     uint8_t data[XRES_LENGTH_MAX];
 } res_t;
 
@@ -151,11 +92,11 @@ typedef struct eutran_vector_s {
     uint8_t kasme[KASME_LENGTH_OCTETS];
 
     /* one UE can have multiple vectors so use STAILQ lists for easy management */
+#if 0
     STAILQ_ENTRY(eutran_vector_s) entries;
+#endif
 } eutran_vector_t;
 
-#endif /* defined(ENABLE_GMP_TYPES) */
-
 #define FC_KASME        (0x10)
 #define FC_KENB         (0x11)
 #define FC_NH           (0x12)
diff --git a/openair-cn/MME_APP/Makefile.am b/openair-cn/MME_APP/Makefile.am
index 6ee2feae263..89abde0d8ff 100644
--- a/openair-cn/MME_APP/Makefile.am
+++ b/openair-cn/MME_APP/Makefile.am
@@ -20,4 +20,5 @@ libmmeapp_la_SOURCES = \
 	mme_app_authentication.c	\
 	mme_app_statistics.c	mme_app_statistics.h	\
 	mme_app_defs.h	mme_app_extern.h	\
+	mme_app_itti_messaging.h	\
 	s6a_2_nas_cause.c
diff --git a/openair-cn/MME_APP/mme_app_authentication.c b/openair-cn/MME_APP/mme_app_authentication.c
index 448c9872360..d0ed75c1499 100644
--- a/openair-cn/MME_APP/mme_app_authentication.c
+++ b/openair-cn/MME_APP/mme_app_authentication.c
@@ -31,8 +31,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "intertask_interface.h"
+#include "mme_app_itti_messaging.h"
 
 #include "mme_config.h"
 
@@ -56,8 +58,6 @@ int mme_app_request_authentication_info(const mme_app_imsi_t imsi,
 
     message_p = itti_alloc_new_message(TASK_MME_APP, S6A_AUTH_INFO_REQ);
 
-    if (message_p == NULL) return -1;
-
     auth_info_req = &message_p->ittiMsg.s6a_auth_info_req;
     MME_APP_IMSI_TO_STRING(imsi, auth_info_req->imsi);
     memcpy(&auth_info_req->visited_plmn, plmn, sizeof(plmn_t));
@@ -77,7 +77,8 @@ int mme_app_handle_nas_auth_resp(nas_auth_resp_t *nas_auth_resp_p)
 
     MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
 
-    if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi)) == NULL) {
+    if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts,
+                      imsi)) == NULL) {
         MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
         return -1;
     }
@@ -111,39 +112,26 @@ int mme_app_handle_nas_auth_resp(nas_auth_resp_t *nas_auth_resp_p)
     return -1;
 }
 
-int mme_app_handle_authentication_info_answer(s6a_auth_info_ans_t *s6a_auth_info_ans_p)
+int mme_app_handle_authentication_info_answer(s6a_auth_info_ans_t
+        *s6a_auth_info_ans_p)
 {
     struct ue_context_s *ue_context;
     uint64_t imsi;
 
-    nas_auth_req_t *nas_auth_req_p;
-    MessageDef     *message_p = NULL;
-
     DevAssert(s6a_auth_info_ans_p != NULL);
 
-    message_p = itti_alloc_new_message(TASK_MME_APP, NAS_AUTHENTICATION_REQ);
-
-    if (message_p == NULL) {
-        return -1;
-    }
-
-    nas_auth_req_p = &message_p->ittiMsg.nas_auth_req;
-
     MME_APP_STRING_TO_IMSI((char *)s6a_auth_info_ans_p->imsi, &imsi);
 
     MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
 
-    memcpy(nas_auth_req_p->imsi, s6a_auth_info_ans_p->imsi, 16);
-
-    if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi)) == NULL) {
+    if ((ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts,
+                      imsi)) == NULL) {
         MME_APP_ERROR("That's embarrassing as we don't know this IMSI\n");
-        free(message_p);
         return -1;
     }
 
     if ((s6a_auth_info_ans_p->result.present == S6A_RESULT_BASE) &&
-        (s6a_auth_info_ans_p->result.choice.base == DIAMETER_SUCCESS))
-    {
+            (s6a_auth_info_ans_p->result.choice.base == DIAMETER_SUCCESS)) {
         /* S6A procedure has succeeded.
          * We have to request UE authentication.
          */
@@ -151,28 +139,37 @@ int mme_app_handle_authentication_info_answer(s6a_auth_info_ans_t *s6a_auth_info
         /* Check that list is not empty and contain only one element */
         DevCheck(s6a_auth_info_ans_p->auth_info.nb_of_vectors == 1,
                  s6a_auth_info_ans_p->auth_info.nb_of_vectors, 1, 0);
-        DevAssert(!STAILQ_EMPTY(&s6a_auth_info_ans_p->auth_info.e_utran_vectors));
 
-        /* Concat both lists */
-        STAILQ_CONCAT(&ue_context->vector_list,
-                      &s6a_auth_info_ans_p->auth_info.e_utran_vectors);
-
-        ue_context->nb_of_vectors += s6a_auth_info_ans_p->auth_info.nb_of_vectors;
+        if (ue_context->vector_list == NULL) {
+            ue_context->vector_list = malloc(sizeof(eutran_vector_t));
+            DevAssert(ue_context->vector_list != NULL);
+        } else {
+            /* Some vector already exist */
+            ue_context->vector_list = realloc(ue_context->vector_list,
+                                              (ue_context->nb_of_vectors + 1) * sizeof(eutran_vector_t));
+            DevAssert(ue_context->vector_list != NULL);
+        }
+        memcpy(&ue_context->vector_list[ue_context->nb_of_vectors],
+               &s6a_auth_info_ans_p->auth_info.eutran_vector, sizeof(eutran_vector_t));
 
-        nas_auth_req_p->failure = NAS_FAILURE_OK;
+        ue_context->vector_in_use = &ue_context->vector_list[ue_context->nb_of_vectors];
 
-        ue_context->vector_in_use = STAILQ_FIRST(&ue_context->vector_list);
+        ue_context->nb_of_vectors += s6a_auth_info_ans_p->auth_info.nb_of_vectors;
 
-//         mme_app_dump_ue_contexts();
+        mme_app_itti_auth_rsp(ue_context->ue_id, 1,
+                              &s6a_auth_info_ans_p->auth_info.eutran_vector);
     } else {
-        //         nas_auth_req_p->failure = NAS_FAILURE_IND;
-        //         nas_auth_req_p->cause = s6a_error_2_nas_cause(
-//             s6a_auth_info_ans_p->result.choice.base, 0);
-        DevMessage("TODO: Handle s6a_auth_info_ans_p->result.present "
-                   "!= S6A_RESULT_BASE");
+        /* Inform NAS layer with the right failure */
+        if (s6a_auth_info_ans_p->result.present == S6A_RESULT_BASE) {
+            mme_app_itti_auth_fail(ue_context->ue_id, s6a_error_2_nas_cause(
+                s6a_auth_info_ans_p->result.choice.base, 0));
+        } else {
+            mme_app_itti_auth_fail(ue_context->ue_id, s6a_error_2_nas_cause(
+                s6a_auth_info_ans_p->result.choice.experimental, 1));
+        }
     }
 
-    return itti_send_msg_to_task(TASK_NAS, INSTANCE_DEFAULT, message_p);
+    return 0;
 }
 
 #if defined(DISABLE_USE_NAS)
@@ -227,16 +224,14 @@ int mme_app_handle_attach_req(nas_attach_req_t *attach_req_p)
         ue_context->mme_ue_s1ap_id = attach_req_p->transparent.mme_ue_s1ap_id;
 
         if ((ue_context->imsi_auth == IMSI_AUTHENTICATED) &&
-            (attach_req_p->initial != INITIAL_REQUEST))
-        {
+                (attach_req_p->initial != INITIAL_REQUEST)) {
             /* We have to send an update location request to the HSS */
             MME_APP_DEBUG("UE is authenticated\n");
         } else {
             MME_APP_DEBUG("UE is not authenticated\n");
             /* UE is not authenticated or an initial request */
             if (STAILQ_EMPTY(&ue_context->vector_list))
-request_auth:
-            {
+request_auth: {
                 /* We have no vector for this UE, send an authentication request
                  * to the HSS.
                  */
@@ -250,7 +245,7 @@ request_auth:
                 };
 
                 memcpy(&ue_context->e_utran_cgi, &attach_req_p->transparent.e_utran_cgi,
-                    sizeof(cgi_t));
+                       sizeof(cgi_t));
 
                 /* Acquire the current time */
                 time(&ue_context->cell_age);
@@ -270,8 +265,8 @@ request_auth:
                 MessageDef     *message_p;
                 /* We have a vector... USE it */
                 MME_APP_DEBUG("but we have an auth. vector for it, request"
-                " authentication from NAS\n");
-                message_p = itti_alloc_new_message(TASK_MME_APP, NAS_AUTHENTICATION_REQ);
+                              " authentication from NAS\n");
+                message_p = itti_alloc_new_message(TASK_MME_APP, NAS_AUTHENTICATION_PARAM_FAIL);
 
                 nas_auth_req_p = &message_p->ittiMsg.nas_auth_req;
 
@@ -284,4 +279,60 @@ request_auth:
     }
     return 0;
 }
+#else
+void mme_app_handle_nas_auth_param_req(nas_auth_param_req_t
+                                       *nas_auth_param_req_p)
+{
+    struct ue_context_s *ue_context;
+    uint64_t imsi = 0;
+
+    DevAssert(nas_auth_param_req_p != NULL);
+
+    MME_APP_STRING_TO_IMSI(nas_auth_param_req_p->imsi, &imsi);
+
+    MME_APP_DEBUG("Handling imsi %"IMSI_FORMAT"\n", imsi);
+
+    /* Fetch the context associated with this IMSI */
+    ue_context = mme_ue_context_exists_imsi(&mme_app_desc.mme_ue_contexts, imsi);
+
+    if (ue_context == NULL) {
+        /* Currently no context available -> trigger an authentication request
+         * to the HSS.
+         */
+        MME_APP_DEBUG("UE context doesn't exist -> create one\n");
+        if ((ue_context = mme_create_new_ue_context()) == NULL) {
+            /* Error during ue context malloc */
+            /* TODO */
+            DevMessage("mme_create_new_ue_context");
+            return;
+        }
+
+        ue_context->imsi  = imsi;
+        ue_context->ue_id = nas_auth_param_req_p->ue_id;
+
+        DevAssert(mme_insert_ue_context(&mme_app_desc.mme_ue_contexts, ue_context) == 0);
+
+        /* We have no vector for this UE, send an authentication request
+         * to the HSS.
+         */
+        plmn_t plmn = {
+            .MCCdigit2 = 0,
+            .MCCdigit1 = 8,
+            .MCCdigit3 = 2,
+            .MNCdigit1 = 0,
+            .MNCdigit2 = 4,
+            .MNCdigit3 = 3,
+        };
+
+        /* Acquire the current time */
+        time(&ue_context->cell_age);
+
+        memcpy(&ue_context->guti.gummei.plmn, &plmn, sizeof(plmn_t));
+        MME_APP_DEBUG("and we have no auth. vector for it, request"
+                      " authentication information\n");
+        mme_app_request_authentication_info(imsi, 1, &plmn);
+    } else {
+        DevMessage("not handled\n");
+    }
+}
 #endif
diff --git a/openair-cn/MME_APP/mme_app_context.c b/openair-cn/MME_APP/mme_app_context.c
index fe1d37a6004..613dfcc2d77 100644
--- a/openair-cn/MME_APP/mme_app_context.c
+++ b/openair-cn/MME_APP/mme_app_context.c
@@ -190,7 +190,6 @@ void mme_app_dump_ue_contexts(mme_ue_context_t *mme_ue_context)
     MME_APP_DEBUG("-----------------------UE contexts-----------------------\n");
     RB_FOREACH(context_p, ue_context_map, &mme_ue_context->ue_context_tree)
     {
-        struct eutran_vector_s *vector_p;
         uint8_t j;
 
         MME_APP_DEBUG("    - IMSI ...........: %"SCNu64"\n", context_p->imsi);
@@ -252,10 +251,13 @@ void mme_app_dump_ue_contexts(mme_ue_context_t *mme_ue_context)
             MME_APP_DEBUG("        Allocated ....: (%010"PRIu64"|%010"PRIu64")\n",
                           context_p->used_ambr.br_dl, context_p->used_ambr.br_ul);
             MME_APP_DEBUG("    - Known vectors ..: %u\n", context_p->nb_of_vectors);
-            STAILQ_FOREACH(vector_p, &context_p->vector_list, entries)
+            for (j = 0; j < context_p->nb_of_vectors; j++)
             {
                 int k;
                 char xres_string[3 * XRES_LENGTH_MAX + 1];
+                eutran_vector_t *vector_p;
+
+                vector_p = &context_p->vector_list[j];
 
                 MME_APP_DEBUG("        - RAND ..: "RAND_FORMAT"\n",
                             RAND_DISPLAY(vector_p->rand));
diff --git a/openair-cn/MME_APP/mme_app_defs.h b/openair-cn/MME_APP/mme_app_defs.h
index d5e023cac29..829c6adc74f 100644
--- a/openair-cn/MME_APP/mme_app_defs.h
+++ b/openair-cn/MME_APP/mme_app_defs.h
@@ -33,6 +33,7 @@
  * Use mme_app_extern.h to expose mme applicative layer procedures/data.
  */
 
+#include "intertask_interface.h"
 #include "mme_app_ue_context.h"
 
 #ifndef MME_APP_DEFS_H_
@@ -69,6 +70,8 @@ int mme_app_handle_authentication_info_answer(s6a_auth_info_ans_t *s6a_auth_info
 
 int mme_app_handle_nas_auth_resp(nas_auth_resp_t *nas_auth_resp_p);
 
-int s6a_error_2_nas_cause(uint32_t s6a_error, int experimental);
+nas_cause_t s6a_error_2_nas_cause(uint32_t s6a_error, int experimental);
+
+void mme_app_handle_nas_auth_param_req(nas_auth_param_req_t *nas_auth_param_req);
 
 #endif /* MME_APP_DEFS_H_ */
diff --git a/openair-cn/MME_APP/mme_app_main.c b/openair-cn/MME_APP/mme_app_main.c
index 9bb8f130f4a..38209421b6e 100644
--- a/openair-cn/MME_APP/mme_app_main.c
+++ b/openair-cn/MME_APP/mme_app_main.c
@@ -78,14 +78,18 @@ void *mme_app_thread(void *args)
                 mme_app_handle_create_sess_resp(&received_message_p->ittiMsg.sgwCreateSessionResponse);
             } break;
 
-            case NAS_AUTHENTICATION_RESP: {
-                mme_app_handle_nas_auth_resp(&received_message_p->ittiMsg.nas_auth_resp);
+            case NAS_AUTHENTICATION_PARAM_REQ: {
+                mme_app_handle_nas_auth_param_req(&received_message_p->ittiMsg.nas_auth_param_req);
             } break;
 
 #if defined(DISABLE_USE_NAS)
             case NAS_ATTACH_REQ: {
                 mme_app_handle_attach_req(&received_message_p->ittiMsg.nas_attach_req);
             } break;
+
+            case NAS_AUTHENTICATION_RESP: {
+                mme_app_handle_nas_auth_resp(&received_message_p->ittiMsg.nas_auth_resp);
+            } break;
 #endif
 
             case TIMER_HAS_EXPIRED: {
diff --git a/openair-cn/MME_APP/mme_app_ue_context.h b/openair-cn/MME_APP/mme_app_ue_context.h
index 45173eeca46..cf7a2c1dd03 100644
--- a/openair-cn/MME_APP/mme_app_ue_context.h
+++ b/openair-cn/MME_APP/mme_app_ue_context.h
@@ -92,6 +92,9 @@ typedef struct bearer_context_s {
  * according to 3GPP TS.23.401 #5.7.2
  */
 typedef struct ue_context_s {
+    /* Tree entry */
+    RB_ENTRY(ue_context_s) rb_entry;
+
     /* Basic identifier for ue. IMSI is encoded on maximum of 15 digits of 4 bits,
      * so usage of an unsigned integer on 64 bits is necessary.
      */
@@ -104,11 +107,14 @@ typedef struct ue_context_s {
     unsigned eNB_ue_s1ap_id:24;
     uint32_t mme_ue_s1ap_id;
 
+    /* ue_id is equal to mme_ue_s1ap_id */
+    uint32_t ue_id;
+
     uint8_t nb_of_vectors;
 
-    struct eutran_vector_s *vector_in_use;
     /* List of authentication vectors for E-UTRAN */
-    STAILQ_HEAD(auth_vectors, eutran_vector_s) vector_list;
+    eutran_vector_t  *vector_list;
+    eutran_vector_t  *vector_in_use;
 
 #define SUBSCRIPTION_UNKNOWN    0x0
 #define SUBSCRIPTION_KNOWN      0x1
@@ -160,10 +166,6 @@ typedef struct ue_context_s {
     uint32_t sgw_s11_teid;
 
     bearer_context_t eps_bearers[BEARERS_PER_UE];
-
-    /* Tree entry */
-    RB_ENTRY(ue_context_s) rb_entry;
-
 } ue_context_t;
 
 typedef struct {
diff --git a/openair-cn/MME_APP/s6a_2_nas_cause.c b/openair-cn/MME_APP/s6a_2_nas_cause.c
index 9031c6d0073..e27c55dd6ef 100644
--- a/openair-cn/MME_APP/s6a_2_nas_cause.c
+++ b/openair-cn/MME_APP/s6a_2_nas_cause.c
@@ -31,18 +31,9 @@
 #include "as_message.h"
 #include "common_types.h"
 #include "s6a_defs.h"
+#include "mme_app_defs.h"
 
-// int send_nas_failure(uint32_t nas_cause)
-// {
-//     MessageDef *message_p;
-// 
-//     message_p = itti_alloc_new_message(TASK_MME_APP, TASK_NAS,
-//                                   SGW_CREATE_SESSION_REQUEST);
-// 
-//     return itti_send_msg_to_task(TASK_NAS, message_p);
-// }
-
-int s6a_error_2_nas_cause(uint32_t s6a_error, int experimental)
+nas_cause_t s6a_error_2_nas_cause(uint32_t s6a_error, int experimental)
 {
     if (experimental == 0) {
         /* Base protocol errors */
@@ -53,7 +44,7 @@ int s6a_error_2_nas_cause(uint32_t s6a_error, int experimental)
             case ER_DIAMETER_REALM_NOT_SERVED: /* Fall through */
             /* 5003 */
             case ER_DIAMETER_AUTHORIZATION_REJECTED:
-                return NO_SUITABLE_CELLS_IN_TRACKING_AREA;
+                return NAS_CAUSE_NO_SUITABLE_CELLS_IN_TRACKING_AREA;
             /* 5012 */
             case ER_DIAMETER_UNABLE_TO_COMPLY: /* Fall through */
             /* 5004 */
@@ -66,11 +57,11 @@ int s6a_error_2_nas_cause(uint32_t s6a_error, int experimental)
         switch (s6a_error) {
             /* 5001 */
             case DIAMETER_ERROR_USER_UNKNOWN:
-                return EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED;
+                return NAS_CAUSE_EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED;
             /* TODO: distinguish GPRS_DATA_SUBSCRIPTION */
             /* 5420 */
             case DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION:
-                return NO_SUITABLE_CELLS_IN_TRACKING_AREA;
+                return NAS_CAUSE_NO_SUITABLE_CELLS_IN_TRACKING_AREA;
             /* 5421 */
             case DIAMETER_ERROR_RAT_NOT_ALLOWED:
                 /* One of the following parameter can be sent depending on
@@ -79,10 +70,10 @@ int s6a_error_2_nas_cause(uint32_t s6a_error, int experimental)
                  * TRACKING_AREA_NOT_ALLOWED
                  * NO_SUITABLE_CELLS_IN_TRACKING_AREA
                  */
-                return TRACKING_AREA_NOT_ALLOWED;
+                return NAS_CAUSE_TRACKING_AREA_NOT_ALLOWED;
             /* 5004 without error diagnostic */
             case DIAMETER_ERROR_ROAMING_NOT_ALLOWED:
-                return PLMN_NOT_ALLOWED;
+                return NAS_CAUSE_PLMN_NOT_ALLOWED;
             /* TODO: 5004 with error diagnostic of ODB_HPLMN_APN or
              * ODB_VPLMN_APN
              */
@@ -91,5 +82,5 @@ int s6a_error_2_nas_cause(uint32_t s6a_error, int experimental)
                 break;
         }
     }
-    return NETWORK_FAILURE;
+    return NAS_CAUSE_NETWORK_FAILURE;
 }
diff --git a/openair-cn/Makefile.am b/openair-cn/Makefile.am
index c7e7cc3c1a7..4a69ba53afa 100644
--- a/openair-cn/Makefile.am
+++ b/openair-cn/Makefile.am
@@ -42,7 +42,7 @@ messages.xml:	$(top_srcdir)/INTERTASK_INTERFACE/intertask_interface_types.h $(me
 
 messages_xml.h: messages.xml
 	@echo "Generating $<"
-	@sed -e 's/[ ]*//' -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/"/' messages.xml > messages_xml.h
+	@sed -e 's/[ ]*//' -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' messages.xml > messages_xml.h
 
 clean-local:
 	@rm -rf -v messages.xml messages_xml.h
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c b/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c
index 681a954472f..4161bed1d5b 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/Attach.c
@@ -1143,21 +1143,21 @@ int emm_proc_attach_request(unsigned int ueid, emm_proc_attach_type_t type,
 
 /****************************************************************************
  **                                                                        **
- ** Name:    emm_proc_attach_reject()                                  **
+ ** Name:        emm_proc_attach_reject()                                  **
  **                                                                        **
  ** Description: Performs the protocol error abnormal case                 **
  **                                                                        **
  **              3GPP TS 24.301, section 5.5.1.2.7, case b                 **
- **      If the ATTACH REQUEST message is received with a protocol **
- **      error, the network shall return an ATTACH REJECT message. **
+ **              If the ATTACH REQUEST message is received with a protocol **
+ **              error, the network shall return an ATTACH REJECT message. **
  **                                                                        **
- ** Inputs:  ueid:      UE lower layer identifier                  **
- **          emm_cause: EMM cause code to be reported              **
- **      Others:    None                                       **
+ ** Inputs:  ueid:              UE lower layer identifier                  **
+ **                  emm_cause: EMM cause code to be reported              **
+ **                  Others:    None                                       **
  **                                                                        **
  ** Outputs:     None                                                      **
- **      Return:    RETURNok, RETURNerror                      **
- **      Others:    _emm_data                                  **
+ **                  Return:    RETURNok, RETURNerror                      **
+ **                  Others:    _emm_data                                  **
  **                                                                        **
  ***************************************************************************/
 int emm_proc_attach_reject(unsigned int ueid, int emm_cause)
@@ -1174,7 +1174,7 @@ int emm_proc_attach_reject(unsigned int ueid, int emm_cause)
 
     /* Update the EMM cause code */
 #if defined(EPC_BUILD)
-    if (ueid == 0)
+    if (ueid > 0)
 #else
     if (ueid < EMM_DATA_NB_UE_MAX)
 #endif
@@ -1828,33 +1828,39 @@ static int _emm_attach_abort(void *args)
  ***************************************************************************/
 static int _emm_attach_identify(void *args)
 {
-    LOG_FUNC_IN;
-
     int rc = RETURNerror;
     emm_data_context_t *emm_ctx = (emm_data_context_t *)(args);
     int guti_reallocation = FALSE;
 
+    LOG_FUNC_IN;
+
     LOG_TRACE(INFO, "EMM-PROC  - Identify incoming UE (ueid=0x%08x) using %s",
               emm_ctx->ueid, (emm_ctx->imsi)? "IMSI" : (emm_ctx->guti)? "GUTI" :
               (emm_ctx->imei)? "IMEI" : "none");
 
-#if defined(EPC_BUILD)
-    nas_itti_auth_info_req(emm_ctx->imsi, 1);
-#endif
-
     /*
      * UE's identification
      * -------------------
      */
     if (emm_ctx->imsi) {
         /* The UE identifies itself using an IMSI */
-        rc = mme_api_identify_imsi(emm_ctx->imsi, &emm_ctx->vector);
-        if (rc != RETURNok) {
-            LOG_TRACE(WARNING, "EMM-PROC  - "
-                      "Failed to identify the UE using provided IMSI");
-            emm_ctx->emm_cause = EMM_CAUSE_ILLEGAL_UE;
+#if defined(EPC_BUILD)
+        if (!emm_ctx->security) {
+            /* Ask upper layer to fetch new security context */
+            nas_itti_auth_info_req(emm_ctx->ueid, emm_ctx->imsi, 1);
+
+            rc = RETURNok;
+        } else
+#endif
+        {
+            rc = mme_api_identify_imsi(emm_ctx->imsi, &emm_ctx->vector);
+            if (rc != RETURNok) {
+                LOG_TRACE(WARNING, "EMM-PROC  - "
+                        "Failed to identify the UE using provided IMSI");
+                emm_ctx->emm_cause = EMM_CAUSE_ILLEGAL_UE;
+            }
+            guti_reallocation = TRUE;
         }
-        guti_reallocation = TRUE;
     } else if (emm_ctx->guti) {
         /* The UE identifies itself using a GUTI */
         rc = mme_api_identify_guti(emm_ctx->guti, &emm_ctx->vector);
@@ -1945,7 +1951,9 @@ static int _emm_attach_identify(void *args)
              * execution of the security mode control procedure.
              */
             rc = _emm_attach_security(emm_ctx);
-        } else {
+        }
+#if !defined(EPC_BUILD)
+        else {
             /* 3GPP TS 24.401, Figure 5.3.2.1-1, point 5a
              * No EMM context exists for the UE in the network; authentication
              * and NAS security setup to activate integrity protection and NAS
@@ -1956,7 +1964,7 @@ static int _emm_attach_identify(void *args)
             const OctetString autn = {AUTH_AUTN_SIZE, (uint8_t *)auth->autn};
             rc = emm_proc_authentication(emm_ctx->ueid, 0, // TODO: eksi != 0
                                          &loc_rand, &autn,
-                                         _emm_attach_security,
+                                         emm_attach_security,
                                          _emm_attach_release,
                                          _emm_attach_release);
             if (rc != RETURNok) {
@@ -1966,6 +1974,7 @@ static int _emm_attach_identify(void *args)
                 emm_ctx->emm_cause = EMM_CAUSE_ILLEGAL_UE;
             }
         }
+#endif
     }
 
     if (rc != RETURNok) {
@@ -1977,18 +1986,25 @@ static int _emm_attach_identify(void *args)
 
 /****************************************************************************
  **                                                                        **
- ** Name:    _emm_attach_security()                                    **
+ ** Name:        _emm_attach_security()                                    **
  **                                                                        **
  ** Description: Initiates security mode control EMM common procedure.     **
  **                                                                        **
- ** Inputs:  args:      security argument parameters               **
- **      Others:    None                                       **
+ ** Inputs:          args:      security argument parameters               **
+ **                  Others:    None                                       **
  **                                                                        **
  ** Outputs:     None                                                      **
- **      Return:    RETURNok, RETURNerror                      **
- **      Others:    _emm_data                                  **
+ **                  Return:    RETURNok, RETURNerror                      **
+ **                  Others:    _emm_data                                  **
  **                                                                        **
  ***************************************************************************/
+#if defined(EPC_BUILD)
+int emm_attach_security(void *args)
+{
+    return _emm_attach_security(args);
+}
+#endif
+
 static int _emm_attach_security(void *args)
 {
     LOG_FUNC_IN;
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/emm_proc.h b/openair-cn/NAS/EURECOM-NAS/src/emm/emm_proc.h
index 9f24fa67ad7..44b7b8ab663 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/emm_proc.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/emm_proc.h
@@ -199,6 +199,8 @@ int emm_proc_authentication(unsigned int ueid, int ksi,
                             emm_common_failure_callback_t failure);
 int emm_proc_authentication_complete(unsigned int ueid, int emm_cause,
                                      const OctetString *res);
+
+int emm_attach_security(void *args);
 #endif
 
 /*
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 47b80210dd7..5b3c7c28b75 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
@@ -1078,6 +1078,12 @@ static int _emm_as_send(const emm_as_t *msg)
     /* Send the message to the Access Stratum or S1AP in case of MME */
     if (as_msg.msgID > 0) {
 #if defined(EPC_BUILD) && defined(NAS_MME)
+        LOG_TRACE(DEBUG, "EMMAS-SAP - "
+                  "Sending msg with id 0x%x, primitive %s (%d) to S1AP layer for transmission",
+                  as_msg.msgID,
+                  _emm_as_primitive_str[msg->primitive - _EMMAS_START - 1],
+                  msg->primitive);
+
         switch (as_msg.msgID) {
             case AS_DL_INFO_TRANSFER_REQ: {
                 nas_itti_dl_data_req(as_msg.msg.dl_info_transfer_req.UEid,
@@ -1086,14 +1092,14 @@ static int _emm_as_send(const emm_as_t *msg)
             } break;
 
             case AS_NAS_ESTABLISH_RSP: {
-                /* The attach procedure succeeded wihtin MME.
-                 * This message should trigger an S1AP initial context setup
-                 * request.
-                 * NOTE: we support only one bearer per message...
-                 */
-//                 nas_itti_establish_cnf(as_msg.msg.nas_establish_cnf.errCode,
-//                                        as_msg.msg.nas_establish_cnf.nasMsg.data,
-//                                        as_msg.msg.nas_establish_cnf.nasMsg.length);
+                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);
+                    LOG_FUNC_RETURN (RETURNok);
+                } else {
+                    /* Handle success case */
+                }
             } break;
 
             default:
@@ -1679,13 +1685,14 @@ static int _emm_as_establish_cnf(const emm_as_establish_t *msg,
 static int _emm_as_establish_rej(const emm_as_establish_t *msg,
                                  nas_establish_rsp_t *as_msg)
 {
-    LOG_FUNC_IN;
-
+    EMM_msg *emm_msg;
     int size = 0;
+    nas_message_t nas_msg;
+
+    LOG_FUNC_IN;
 
     LOG_TRACE(INFO, "EMMAS-SAP - Send AS connection establish reject");
 
-    nas_message_t nas_msg;
     memset(&nas_msg, 0 , sizeof(nas_message_t));
 
     /* Setup the AS message */
@@ -1697,7 +1704,7 @@ static int _emm_as_establish_rej(const emm_as_establish_t *msg,
     }
 
     /* Setup the NAS security header */
-    EMM_msg *emm_msg = _emm_as_set_header(&nas_msg, &msg->sctx);
+    emm_msg = _emm_as_set_header(&nas_msg, &msg->sctx);
 
     /* Setup the NAS information message */
     if (emm_msg != NULL) switch (msg->NASinfo) {
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
new file mode 100644
index 00000000000..37728ff8191
--- /dev/null
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.c
@@ -0,0 +1,134 @@
+/*****************************************************************************
+            Eurecom OpenAirInterface 3
+            Copyright(c) 2012 Eurecom
+
+Source      emm_cn.c
+
+Version     0.1
+
+Date        2013/12/05
+
+Product     NAS stack
+
+Subsystem   EPS Core Network
+
+Author      Sebastien Roux
+
+Description
+
+*****************************************************************************/
+
+#include <string.h>
+
+#include "nas_log.h"
+#include "commonDef.h"
+
+#include "emm_cn.h"
+#include "emm_sap.h"
+#include "emm_proc.h"
+#include "emm_cause.h"
+
+/*
+ * String representation of EMMCN-SAP primitives
+ */
+static const char *_emm_cn_primitive_str[] = {
+    "EMMCN_AUTHENTICATION_PARAM_RES",
+    "EMMCN_AUTHENTICATION_PARAM_FAIL",
+};
+
+static int _emm_cn_authentication_res(const emm_cn_auth_res_t *msg)
+{
+    emm_data_context_t *emm_ctx = NULL;
+    int rc = RETURNerror;
+    OctetString loc_rand;
+    OctetString autn;
+
+    /* We received security vector from HSS. Try to setup security with UE */
+
+    LOG_FUNC_IN;
+
+    emm_ctx = emm_data_context_get(&_emm_data, msg->ue_id);
+    if (emm_ctx == NULL) {
+        LOG_TRACE(ERROR, "EMM-PROC  - "
+                  "Failed to find UE associated to id %u...", msg->ue_id);
+        LOG_FUNC_RETURN (rc);
+    }
+
+    /* Copy provided vector to user context */
+    memcpy(emm_ctx->vector.kasme, msg->vector.kasme,     AUTH_KASME_SIZE);
+    memcpy(emm_ctx->vector.autn,  msg->vector.autn,      AUTH_AUTN_SIZE);
+    memcpy(emm_ctx->vector.rand,  msg->vector.rand,      AUTH_RAND_SIZE);
+    memcpy(emm_ctx->vector.xres,  msg->vector.xres.data, msg->vector.xres.size);
+
+    loc_rand.value  = emm_ctx->vector.rand;
+    loc_rand.length = AUTH_RAND_SIZE;
+
+    autn.value  = emm_ctx->vector.autn;
+    autn.length = AUTH_AUTN_SIZE;
+
+    emm_ctx->vector.xres_size = msg->vector.xres.size;
+
+    /* 3GPP TS 24.401, Figure 5.3.2.1-1, point 5a
+     * No EMM context exists for the UE in the network; authentication
+     * and NAS security setup to activate integrity protection and NAS
+     * ciphering are mandatory.
+     */
+    rc = emm_proc_authentication(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  - "
+        "Failed to initiate authentication procedure");
+        emm_ctx->emm_cause = EMM_CAUSE_ILLEGAL_UE;
+    }
+
+    LOG_FUNC_RETURN (rc);
+}
+
+static int _emm_cn_authentication_fail(const emm_cn_auth_fail_t *msg)
+{
+    int rc = RETURNerror;
+
+    LOG_FUNC_IN;
+
+    rc = emm_proc_attach_reject(msg->ue_id, msg->cause);
+
+    LOG_FUNC_RETURN (rc);
+}
+
+int emm_cn_send(const emm_cn_t *msg)
+{
+    int rc = RETURNerror;
+    emm_cn_primitive_t primitive = msg->primitive;
+
+    LOG_FUNC_IN;
+
+    LOG_TRACE(INFO, "EMMCN-SAP - Received primitive %s (%d)",
+              _emm_cn_primitive_str[primitive - _EMMCN_START - 1], primitive);
+
+    switch (primitive) {
+        case _EMMCN_AUTHENTICATION_PARAM_RES:
+            rc = _emm_cn_authentication_res(msg->u.auth_res);
+            break;
+
+        case _EMMCN_AUTHENTICATION_PARAM_FAIL:
+            rc = _emm_cn_authentication_fail(msg->u.auth_fail);
+            break;
+
+        default:
+            /* Other primitives are forwarded to the Access Stratum */
+            rc = RETURNerror;
+            break;
+    }
+
+    if (rc != RETURNok) {
+        LOG_TRACE(ERROR, "EMMCN-SAP - Failed to process primitive %s (%d)",
+                  _emm_cn_primitive_str[primitive - _EMMCN_START - 1],
+                  primitive);
+    }
+
+    LOG_FUNC_RETURN (rc);
+}
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.h b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.h
new file mode 100644
index 00000000000..143fc77e341
--- /dev/null
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cn.h
@@ -0,0 +1,28 @@
+/*****************************************************************************
+            Eurecom OpenAirInterface 3
+            Copyright(c) 2013 Eurecom
+
+Source      emm_cn.h
+
+Version     0.1
+
+Date        2013/12/05
+
+Product     NAS stack
+
+Subsystem   EPS Core Network
+
+Author      Sebastien Roux
+
+Description
+
+*****************************************************************************/
+
+#include "emm_cnDef.h"
+
+#ifndef _EMM_CN_H_
+#define _EMM_CN_H_
+
+int emm_cn_send(const emm_cn_t *msg);
+
+#endif /* _EMM_CN_H_ */
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cnDef.h b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cnDef.h
new file mode 100644
index 00000000000..577d5c403ad
--- /dev/null
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_cnDef.h
@@ -0,0 +1,48 @@
+/*****************************************************************************
+            Eurecom OpenAirInterface 3
+            Copyright(c) 2012 Eurecom
+
+Source      emm_cnDef.h
+
+Version     0.1
+
+Date        2013/12/05
+
+Product     NAS stack
+
+Subsystem   EPS Core Network
+
+Author      Sebastien Roux
+
+Description
+
+*****************************************************************************/
+
+#include "intertask_interface.h"
+
+#ifndef __EMM_CNDEF_H__
+#define __EMM_CNDEF_H__
+
+typedef enum emmcn_primitive_s {
+    _EMMCN_START = 400,
+#if defined(EPC_BUILD)
+    _EMMCN_AUTHENTICATION_PARAM_RES,
+    _EMMCN_AUTHENTICATION_PARAM_FAIL,
+#endif
+    _EMMCN_END
+} emm_cn_primitive_t;
+
+typedef nas_auth_param_rsp_t  emm_cn_auth_res_t;
+typedef nas_auth_param_fail_t emm_cn_auth_fail_t;
+
+#if defined(EPC_BUILD)
+typedef struct emm_mme_ul_s {
+    emm_cn_primitive_t primitive;
+    union {
+        emm_cn_auth_res_t  *auth_res;
+        emm_cn_auth_fail_t *auth_fail;
+    } u;
+} emm_cn_t;
+#endif
+
+#endif /* __EMM_CNDEF_H__ */
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.c b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.c
index b02b82d87ee..4ab81e9bfdf 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.c
@@ -28,6 +28,7 @@ Description Defines the EMM Service Access Points at which the EPS
 #include "emm_reg.h"
 #include "emm_esm.h"
 #include "emm_as.h"
+#include "emm_cn.h"
 
 /****************************************************************************/
 /****************  E X T E R N A L    D E F I N I T I O N S  ****************/
@@ -82,12 +83,12 @@ void emm_sap_initialize(void)
  ***************************************************************************/
 int emm_sap_send(emm_sap_t *msg)
 {
-    LOG_FUNC_IN;
-
     int rc = RETURNerror;
 
     emm_primitive_t primitive = msg->primitive;
 
+    LOG_FUNC_IN;
+
     /* Check the EMM-SAP primitive */
     if ( (primitive > EMMREG_PRIMITIVE_MIN) &&
             (primitive < EMMREG_PRIMITIVE_MAX) ) {
@@ -104,7 +105,16 @@ int emm_sap_send(emm_sap_t *msg)
         /* Forward to the EMMAS-SAP */
         msg->u.emm_as.primitive = primitive;
         rc = emm_as_send(&msg->u.emm_as);
-    } else {
+    }
+#if defined(EPC_BUILD)
+    else if ( (primitive > EMMCN_PRIMITIVE_MIN) &&
+              (primitive < EMMCN_PRIMITIVE_MAX) ) {
+        /* Forward to the EMMCN-SAP */
+        msg->u.emm_cn.primitive = primitive;
+        rc = emm_cn_send(&msg->u.emm_cn);
+    }
+#endif
+    else {
         LOG_TRACE(WARNING, "EMM-SAP -   Out of range primitive (%d)", primitive);
     }
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.h b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.h
index 12a43bc3c33..e5291572c21 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/emm/sap/emm_sap.h
@@ -26,6 +26,7 @@ Description Defines the EMM Service Access Points at which the EPS
 #include "emm_regDef.h"
 #include "emm_esmDef.h"
 #include "emm_asDef.h"
+#include "emm_cnDef.h"
 
 /****************************************************************************/
 /*********************  G L O B A L    C O N S T A N T S  *******************/
@@ -46,8 +47,8 @@ typedef enum {
 #ifdef NAS_UE
     EMMREG_S1_ENABLED       = _EMMREG_S1_ENABLED,
     EMMREG_S1_DISABLED      = _EMMREG_S1_DISABLED,
-    EMMREG_NO_IMSI      = _EMMREG_NO_IMSI,
-    EMMREG_NO_CELL      = _EMMREG_NO_CELL,
+    EMMREG_NO_IMSI          = _EMMREG_NO_IMSI,
+    EMMREG_NO_CELL          = _EMMREG_NO_CELL,
     EMMREG_REGISTER_REQ     = _EMMREG_REGISTER_REQ,
     EMMREG_REGISTER_CNF     = _EMMREG_REGISTER_CNF,
     EMMREG_REGISTER_REJ     = _EMMREG_REGISTER_REJ,
@@ -55,7 +56,7 @@ typedef enum {
     EMMREG_ATTACH_REQ       = _EMMREG_ATTACH_REQ,
     EMMREG_ATTACH_FAILED    = _EMMREG_ATTACH_FAILED,
     EMMREG_ATTACH_EXCEEDED  = _EMMREG_ATTACH_EXCEEDED,
-    EMMREG_AUTH_REJ     = _EMMREG_AUTH_REJ,
+    EMMREG_AUTH_REJ         = _EMMREG_AUTH_REJ,
 #endif
 #ifdef NAS_MME
     EMMREG_COMMON_PROC_REQ  = _EMMREG_COMMON_PROC_REQ,
@@ -69,9 +70,9 @@ typedef enum {
     EMMREG_DETACH_REQ       = _EMMREG_DETACH_REQ,
     EMMREG_DETACH_FAILED    = _EMMREG_DETACH_FAILED,
     EMMREG_DETACH_CNF       = _EMMREG_DETACH_CNF,
-    EMMREG_TAU_REQ      = _EMMREG_TAU_REQ,
-    EMMREG_TAU_CNF      = _EMMREG_TAU_CNF,
-    EMMREG_TAU_REJ      = _EMMREG_TAU_REJ,
+    EMMREG_TAU_REQ          = _EMMREG_TAU_REQ,
+    EMMREG_TAU_CNF          = _EMMREG_TAU_CNF,
+    EMMREG_TAU_REJ          = _EMMREG_TAU_REJ,
     EMMREG_SERVICE_REQ      = _EMMREG_SERVICE_REQ,
     EMMREG_SERVICE_CNF      = _EMMREG_SERVICE_CNF,
     EMMREG_SERVICE_REJ      = _EMMREG_SERVICE_REJ,
@@ -97,13 +98,18 @@ typedef enum {
     EMMAS_ESTABLISH_REJ     = _EMMAS_ESTABLISH_REJ,
     EMMAS_RELEASE_REQ       = _EMMAS_RELEASE_REQ,
     EMMAS_RELEASE_IND       = _EMMAS_RELEASE_IND,
-    EMMAS_DATA_REQ      = _EMMAS_DATA_REQ,
-    EMMAS_DATA_IND      = _EMMAS_DATA_IND,
-    EMMAS_PAGE_IND      = _EMMAS_PAGE_IND,
+    EMMAS_DATA_REQ          = _EMMAS_DATA_REQ,
+    EMMAS_DATA_IND          = _EMMAS_DATA_IND,
+    EMMAS_PAGE_IND          = _EMMAS_PAGE_IND,
     EMMAS_STATUS_IND        = _EMMAS_STATUS_IND,
     EMMAS_CELL_INFO_REQ     = _EMMAS_CELL_INFO_REQ,
     EMMAS_CELL_INFO_RES     = _EMMAS_CELL_INFO_RES,
     EMMAS_CELL_INFO_IND     = _EMMAS_CELL_INFO_IND,
+
+#ifdef EPC_BUILD
+    EMMCN_AUTHENTICATION_PARAM_RES      = _EMMCN_AUTHENTICATION_PARAM_RES,
+    EMMCN_AUTHENTICATION_PARAM_FAIL     = _EMMCN_AUTHENTICATION_PARAM_FAIL,
+#endif
 } emm_primitive_t;
 
 /*
@@ -111,14 +117,16 @@ typedef enum {
  */
 #define EMMREG_PRIMITIVE_MIN    _EMMREG_START
 #define EMMESM_PRIMITIVE_MIN    _EMMESM_START
-#define EMMAS_PRIMITIVE_MIN _EMMAS_START
+#define EMMAS_PRIMITIVE_MIN     _EMMAS_START
+#define EMMCN_PRIMITIVE_MIN     _EMMCN_START
 
 /*
  * Maximal identifier for EMM-SAP primitives
  */
 #define EMMREG_PRIMITIVE_MAX    _EMMREG_END
 #define EMMESM_PRIMITIVE_MAX    _EMMESM_END
-#define EMMAS_PRIMITIVE_MAX _EMMAS_END
+#define EMMAS_PRIMITIVE_MAX     _EMMAS_END
+#define EMMCN_PRIMITIVE_MAX     _EMMCN_END
 
 /****************************************************************************/
 /************************  G L O B A L    T Y P E S  ************************/
@@ -133,6 +141,9 @@ typedef struct {
         emm_reg_t emm_reg;  /* EMMREG-SAP primitives    */
         emm_esm_t emm_esm;  /* EMMESM-SAP primitives    */
         emm_as_t  emm_as;   /* EMMAS-SAP primitives     */
+#if defined(EPC_BUILD)
+        emm_cn_t  emm_cn;   /* EMMCN-SAP primitives     */
+#endif
     } u;
 } emm_sap_t;
 
diff --git a/openair-cn/NAS/EURECOM-NAS/src/include/securityDef.h b/openair-cn/NAS/EURECOM-NAS/src/include/securityDef.h
index fe4412f3516..605f14b71be 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/include/securityDef.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/include/securityDef.h
@@ -42,12 +42,12 @@ Description Contains global security definitions
                 AUTN = (SQN ⊕ AK) || AMF || MAC        */
 #define AUTH_MACS_SIZE  8  /* Re-synchronization MAC:       64 bits  */
 #define AUTH_AUTS_SIZE  16 /* Re-synchronization AUT:       128 bits */
-#define AUTH_RAND_SIZE  16 /* Random challenge:         128 bits */
-#define AUTH_CK_SIZE    16 /* Ciphering key:            128 bits */
-#define AUTH_IK_SIZE    16 /* Integrity key:            128 bits */
+#define AUTH_RAND_SIZE  16 /* Random challenge:         128 bits     */
+#define AUTH_CK_SIZE    16 /* Ciphering key:            128 bits     */
+#define AUTH_IK_SIZE    16 /* Integrity key:            128 bits     */
 #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 /* ASME security key:        256 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_KENB_SIZE      AUTH_KASME_SIZE /* eNodeB security key   */
@@ -64,14 +64,15 @@ Description Contains global security definitions
  */
 typedef struct {
     /* ASME security key                */
-    char kasme[AUTH_KASME_SIZE + 1];
+    uint8_t kasme[AUTH_KASME_SIZE];
     /* Random challenge parameter           */
-    char rand[AUTH_RAND_SIZE + 1];
+    uint8_t rand[AUTH_RAND_SIZE];
     /* Authentication token parameter       */
-    char autn[AUTH_AUTN_SIZE + 1];
+    uint8_t autn[AUTH_AUTN_SIZE];
     /* Expected Authentication response parameter   */
 #define AUTH_XRES_SIZE  AUTH_RES_SIZE
-    char xres[AUTH_XRES_SIZE + 1];
+    uint8_t xres_size;
+    uint8_t xres[AUTH_XRES_SIZE];
 } auth_vector_t;
 
 /****************************************************************************/
diff --git a/openair-cn/NAS/EURECOM-NAS/src/nas_proc.c b/openair-cn/NAS/EURECOM-NAS/src/nas_proc.c
index c7728d8df88..77c07bc88d4 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/nas_proc.c
+++ b/openair-cn/NAS/EURECOM-NAS/src/nas_proc.c
@@ -1421,10 +1421,10 @@ int nas_proc_dl_transfer_rej(UInt32_t ueid)
  ***************************************************************************/
 int nas_proc_ul_transfer_ind(UInt32_t ueid, const Byte_t *data, UInt32_t len)
 {
-    LOG_FUNC_IN;
-
     int rc = RETURNerror;
 
+    LOG_FUNC_IN;
+
     if (len > 0) {
         emm_sap_t emm_sap;
         /*
@@ -1441,6 +1441,38 @@ int nas_proc_ul_transfer_ind(UInt32_t ueid, const Byte_t *data, UInt32_t len)
 
     LOG_FUNC_RETURN (rc);
 }
+
+# if defined(EPC_BUILD)
+int nas_proc_auth_param_res(emm_cn_auth_res_t *emm_cn_auth_res)
+{
+    int rc = RETURNerror;
+    emm_sap_t emm_sap;
+
+    LOG_FUNC_IN;
+
+    emm_sap.primitive = EMMCN_AUTHENTICATION_PARAM_RES;
+    emm_sap.u.emm_cn.u.auth_res = emm_cn_auth_res;
+
+    rc = emm_sap_send(&emm_sap);
+
+    LOG_FUNC_RETURN (rc);
+}
+
+int nas_proc_auth_param_fail(emm_cn_auth_fail_t *emm_cn_auth_fail)
+{
+    int rc = RETURNerror;
+    emm_sap_t emm_sap;
+
+    LOG_FUNC_IN;
+
+    emm_sap.primitive = EMMCN_AUTHENTICATION_PARAM_FAIL;
+    emm_sap.u.emm_cn.u.auth_fail = emm_cn_auth_fail;
+
+    rc = emm_sap_send(&emm_sap);
+
+    LOG_FUNC_RETURN (rc);
+}
+# endif
 #endif // NAS_MME
 
 /****************************************************************************/
diff --git a/openair-cn/NAS/EURECOM-NAS/src/nas_proc.h b/openair-cn/NAS/EURECOM-NAS/src/nas_proc.h
index 205e76e4dc4..158a8540d54 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/nas_proc.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/nas_proc.h
@@ -22,6 +22,7 @@ Description NAS procedure call manager
 
 #if defined(EPC_BUILD)
 # include "mme_config.h"
+# include "emm_cnDef.h"
 #endif
 
 #include "commonDef.h"
@@ -128,4 +129,15 @@ int nas_proc_dl_transfer_rej(UInt32_t ueid);
 int nas_proc_ul_transfer_ind(UInt32_t ueid, const Byte_t *data, UInt32_t len);
 #endif
 
+/*
+ * --------------------------------------------------------------------------
+ *      NAS procedures triggered by the mme applicative layer
+ * --------------------------------------------------------------------------
+ */
+#if defined(NAS_MME) && defined(EPC_BUILD)
+int nas_proc_auth_param_res(emm_cn_auth_res_t *emm_cn_auth_res);
+
+int nas_proc_auth_param_fail(emm_cn_auth_fail_t *emm_cn_auth_fail);
+#endif
+
 #endif /* __NAS_PROC_H__*/
diff --git a/openair-cn/NAS/EURECOM-NAS/src/util/OctetString.h b/openair-cn/NAS/EURECOM-NAS/src/util/OctetString.h
index 82ef86989c5..4dc1715c7c4 100644
--- a/openair-cn/NAS/EURECOM-NAS/src/util/OctetString.h
+++ b/openair-cn/NAS/EURECOM-NAS/src/util/OctetString.h
@@ -4,8 +4,8 @@
 #define OCTET_STRING_H_
 
 typedef struct OctetString_tag {
-        uint32_t  length;
-        uint8_t  *value;
+    uint32_t  length;
+    uint8_t  *value;
 } OctetString;
 
 int encode_octet_string(OctetString *octetstring, uint8_t *buffer, uint32_t len);
diff --git a/openair-cn/NAS/Makefile.inc b/openair-cn/NAS/Makefile.inc
index f1e6d9214e1..771ea1c3036 100644
--- a/openair-cn/NAS/Makefile.inc
+++ b/openair-cn/NAS/Makefile.inc
@@ -90,8 +90,9 @@ libnas_emm_msg_SRCS =           \
     EURECOM-NAS/src/emm/msg/TrackingAreaUpdateComplete.c
 
 libnas_emm_sap_SRCS =           \
-    EURECOM-NAS/src/emm/sap/emm_as.c \        \
     EURECOM-NAS/src/emm/sap/emm_as.c \
+    EURECOM-NAS/src/emm/sap/emm_cn.c \
+    EURECOM-NAS/src/emm/sap/emm_cn.h \
     EURECOM-NAS/src/emm/sap/EmmDeregisteredNoImsi.c \
     EURECOM-NAS/src/emm/sap/emm_reg.c \
     EURECOM-NAS/src/emm/sap/EmmRegisteredUpdateNeeded.c \
diff --git a/openair-cn/NAS/nas_itti_messaging.c b/openair-cn/NAS/nas_itti_messaging.c
index 64ce5074ecd..ddf3bbe04b5 100644
--- a/openair-cn/NAS/nas_itti_messaging.c
+++ b/openair-cn/NAS/nas_itti_messaging.c
@@ -33,7 +33,7 @@
 #include "intertask_interface.h"
 #include "nas_itti_messaging.h"
 
-int nas_itti_dl_data_req(const uint32_t ue_id, void * const data,
+int nas_itti_dl_data_req(const uint32_t ue_id, void *const data,
                          const uint32_t length)
 {
     MessageDef *message_p;
@@ -47,7 +47,7 @@ int nas_itti_dl_data_req(const uint32_t ue_id, void * const data,
     return itti_send_msg_to_task(TASK_S1AP, INSTANCE_DEFAULT, message_p);
 }
 
-void nas_itti_establish_cnf(const nas_error_code_t error_code, void * const data,
+void nas_itti_establish_cnf(const nas_error_code_t error_code, void *const data,
                             const uint32_t length)
 {
     MessageDef *message_p;
diff --git a/openair-cn/NAS/nas_itti_messaging.h b/openair-cn/NAS/nas_itti_messaging.h
index 5f60d505dcc..7f6dba899de 100644
--- a/openair-cn/NAS/nas_itti_messaging.h
+++ b/openair-cn/NAS/nas_itti_messaging.h
@@ -27,6 +27,8 @@
                  06410 Biot FRANCE
 
 *******************************************************************************/
+#include <stdint.h>
+#include <ctype.h>
 
 #include "intertask_interface.h"
 #include "conversions.h"
@@ -34,23 +36,56 @@
 #ifndef NAS_ITTI_MESSAGING_H_
 #define NAS_ITTI_MESSAGING_H_
 
-int nas_itti_dl_data_req(const uint32_t ue_id, void * const data,
+int nas_itti_dl_data_req(const uint32_t ue_id, void *const data,
                          const uint32_t length);
 
-void nas_itti_establish_cnf(const nas_error_code_t error_code, void * const data,
+void nas_itti_establish_cnf(const nas_error_code_t error_code, void *const data,
                             const uint32_t length);
 
-static inline void nas_itti_auth_info_req(const imsi_t * const imsi,
-                                          uint8_t initial_req)
+static inline void nas_itti_auth_info_req(const uint32_t ue_id,
+        const imsi_t *const imsi, uint8_t initial_req)
 {
     MessageDef *message_p;
 
     message_p = itti_alloc_new_message(TASK_NAS, NAS_AUTHENTICATION_PARAM_REQ);
 
-    hexa_to_ascii((uint8_t *)imsi->u.value, NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi,
-                  imsi->length);
+    hexa_to_ascii((uint8_t *)imsi->u.value,
+                  NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi, 8);
+
+    NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi[15] = '\0';
+
+    if (isdigit(NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi[14])) {
+        NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi_length = 15;
+    } else {
+        NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi_length = 14;
+        NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi[14] = '\0';
+    }
+    NAS_AUTHENTICATION_PARAM_REQ(message_p).initial_req = initial_req;
+    NAS_AUTHENTICATION_PARAM_REQ(message_p).ue_id = ue_id;
+
+    itti_send_msg_to_task(TASK_MME_APP, INSTANCE_DEFAULT, message_p);
+}
+
+static inline void nas_itti_establish_rej(const uint32_t ue_id,
+        const imsi_t *const imsi, uint8_t initial_req)
+{
+    MessageDef *message_p;
+
+    message_p = itti_alloc_new_message(TASK_NAS, NAS_AUTHENTICATION_PARAM_REQ);
+
+    hexa_to_ascii((uint8_t *)imsi->u.value,
+                  NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi, 8);
+
+    NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi[15] = '\0';
+
+    if (isdigit(NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi[14])) {
+        NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi_length = 15;
+    } else {
+        NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi_length = 14;
+        NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi[14] = '\0';
+    }
     NAS_AUTHENTICATION_PARAM_REQ(message_p).initial_req = initial_req;
-    NAS_AUTHENTICATION_PARAM_REQ(message_p).imsi_length = imsi->length - imsi->u.num.parity;
+    NAS_AUTHENTICATION_PARAM_REQ(message_p).ue_id = ue_id;
 
     itti_send_msg_to_task(TASK_MME_APP, INSTANCE_DEFAULT, message_p);
 }
diff --git a/openair-cn/NAS/nas_main.c b/openair-cn/NAS/nas_main.c
index a32a494e051..906da44ffc0 100644
--- a/openair-cn/NAS/nas_main.c
+++ b/openair-cn/NAS/nas_main.c
@@ -113,9 +113,7 @@ next_message:
 
                 itti_send_msg_to_task(TASK_MME_APP, INSTANCE_DEFAULT, message_p);
             } break;
-#endif
-
-#if !defined(DISABLE_USE_NAS)
+#else
             case NAS_UPLINK_DATA_IND: {
                 nas_proc_ul_transfer_ind(NAS_UL_DATA_IND(received_message_p).UEid,
                                          NAS_UL_DATA_IND(received_message_p).nasMsg.data,
@@ -125,6 +123,14 @@ next_message:
             case NAS_DOWNLINK_DATA_CNF: {
 //                 nas_proc_dl_transfer_cnf(NAS_DL_DATA_CNF(received_message_p).UEid);
             } break;
+
+            case NAS_AUTHENTICATION_PARAM_RSP: {
+                nas_proc_auth_param_res(&NAS_AUTHENTICATION_PARAM_RSP(received_message_p));
+            } break;
+
+            case NAS_AUTHENTICATION_PARAM_FAIL: {
+                nas_proc_auth_param_fail(&NAS_AUTHENTICATION_PARAM_FAIL(received_message_p));
+            } break;
 #endif
 
             case TERMINATE_MESSAGE: {
@@ -148,7 +154,7 @@ int nas_init(mme_config_t *mme_config_p)
     NAS_DEBUG("Initializing NAS task interface\n");
 
 #if !defined(DISABLE_USE_NAS)
-    nas_log_init(LOG_DEBUG);
+    nas_log_init(0x2F);
     nas_network_initialize(mme_config_p);
 #endif
 
diff --git a/openair-cn/S6A/s6a_auth_info.c b/openair-cn/S6A/s6a_auth_info.c
index a3ebd04711f..e7b900198da 100644
--- a/openair-cn/S6A/s6a_auth_info.c
+++ b/openair-cn/S6A/s6a_auth_info.c
@@ -152,8 +152,6 @@ int s6a_parse_authentication_info_avp(struct avp *avp_auth_info,
     DevCheck(hdr->avp_code == AVP_CODE_AUTHENTICATION_INFO,
              hdr->avp_code, AVP_CODE_AUTHENTICATION_INFO, 0);
 
-    /* Init the list of vectors */
-    STAILQ_INIT(&authentication_info->e_utran_vectors);
     authentication_info->nb_of_vectors = 0;
 
     CHECK_FCT(fd_msg_browse(avp_auth_info, MSG_BRW_FIRST_CHILD, &avp, NULL));
@@ -162,11 +160,8 @@ int s6a_parse_authentication_info_avp(struct avp *avp_auth_info,
 
         switch(hdr->avp_code) {
             case AVP_CODE_E_UTRAN_VECTOR: {
-                struct eutran_vector_s *vector;
-                vector = calloc(1, sizeof(struct eutran_vector_s));
-                CHECK_FCT(s6a_parse_e_utran_vector(avp, vector));
-                STAILQ_INSERT_TAIL(&authentication_info->e_utran_vectors,
-                                    vector, entries);
+                DevAssert(authentication_info->nb_of_vectors == 0);
+                CHECK_FCT(s6a_parse_e_utran_vector(avp, &authentication_info->eutran_vector));
                 authentication_info->nb_of_vectors ++;
             } break;
             default:
@@ -192,6 +187,8 @@ int s6a_aia_cb(struct msg **msg, struct avp *paramavp,
     MessageDef          *message_p;
     s6a_auth_info_ans_t *s6a_auth_info_ans_p;
 
+    int skip_auth_res = 0;
+
     DevAssert(msg != NULL);
 
     ans = *msg;
@@ -240,7 +237,7 @@ int s6a_aia_cb(struct msg **msg, struct avp *paramavp,
             s6a_auth_info_ans_p->result.present = S6A_RESULT_EXPERIMENTAL;
             s6a_parse_experimental_result(avp, &s6a_auth_info_ans_p->result.choice.experimental);
 
-            goto err;
+            skip_auth_res = 1;
         } else {
             /* Neither result-code nor experimental-result is present ->
              * totally incorrect behaviour here.
@@ -250,11 +247,14 @@ int s6a_aia_cb(struct msg **msg, struct avp *paramavp,
             goto err;
         }
     }
-    CHECK_FCT(fd_msg_search_avp(ans, s6a_fd_cnf.dataobj_s6a_authentication_info, &avp));
-    if (avp) {
-        CHECK_FCT(s6a_parse_authentication_info_avp(avp, &s6a_auth_info_ans_p->auth_info));
-    } else {
-        DevMessage("We requested E-UTRAN vectors with an immediate response...\n");
+
+    if (skip_auth_res == 0) {
+        CHECK_FCT(fd_msg_search_avp(ans, s6a_fd_cnf.dataobj_s6a_authentication_info, &avp));
+        if (avp) {
+            CHECK_FCT(s6a_parse_authentication_info_avp(avp, &s6a_auth_info_ans_p->auth_info));
+        } else {
+            DevMessage("We requested E-UTRAN vectors with an immediate response...\n");
+        }
     }
 
     itti_send_msg_to_task(TASK_MME_APP, INSTANCE_DEFAULT, message_p);
-- 
GitLab