From 7fe8d45d6a6a5702076fea08f66ac0aba6ad408c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Leroy?= <frederic.leroy@b-com.com>
Date: Wed, 17 Aug 2016 08:42:37 +0200
Subject: [PATCH] refactor(conf2uedata): move usim_data funcions in
 conf_usim.[c|h]

---
 cmake_targets/nas_sim_tools/CMakeLists.txt |   1 +
 openair3/NAS/TOOLS/conf2uedata.c           | 331 ++-------------------
 openair3/NAS/TOOLS/conf2uedata.h           |  41 +--
 openair3/NAS/TOOLS/conf_emm.c              |   2 +-
 openair3/NAS/TOOLS/conf_emm.h              |   2 +-
 openair3/NAS/TOOLS/conf_usim.c             | 301 +++++++++++++++++++
 openair3/NAS/TOOLS/conf_usim.h             |  45 +++
 7 files changed, 371 insertions(+), 352 deletions(-)
 create mode 100644 openair3/NAS/TOOLS/conf_usim.c
 create mode 100644 openair3/NAS/TOOLS/conf_usim.h

diff --git a/cmake_targets/nas_sim_tools/CMakeLists.txt b/cmake_targets/nas_sim_tools/CMakeLists.txt
index f450715a294..39e71023571 100644
--- a/cmake_targets/nas_sim_tools/CMakeLists.txt
+++ b/cmake_targets/nas_sim_tools/CMakeLists.txt
@@ -19,6 +19,7 @@ set(conf2uedata_SRC
     ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf2uedata.c
     ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_emm.c
     ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_user_data.c
+    ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_usim.c
     ${OPENAIR_DIR}/openair3/NAS/TOOLS/fs.c
     ${OPENAIR_DIR}/openair3/NAS/TOOLS/display.c
     ${OPENAIR_DIR}/openair3/NAS/UE/API/USIM/usim_api.c
diff --git a/openair3/NAS/TOOLS/conf2uedata.c b/openair3/NAS/TOOLS/conf2uedata.c
index 3b31776a029..a3beb27b2d2 100644
--- a/openair3/NAS/TOOLS/conf2uedata.c
+++ b/openair3/NAS/TOOLS/conf2uedata.c
@@ -5,19 +5,12 @@
 
 #include "conf2uedata.h"
 #include "memory.h"
-#include "userDef.h"
-#include "usim_api.h"
 #include "utils.h"
 #include "display.h"
 #include "fs.h"
 #include "conf_emm.h"
 #include "conf_user_data.h"
-
-const char *msin = NULL;
-const char *usim_api_k = NULL;
-const char *msisdn = NULL;
-const char *opc = NULL;
-const char *hplmn = NULL;
+#include "conf_usim.h"
 
 int *ucplmn = NULL;
 int *oplmn = NULL;
@@ -112,10 +105,13 @@ int parse_config_file(const char *output_dir, const char *conf_filename) {
 
     for (int i = 0; i < ue_nb; i++) {
 	    emm_nvdata_t emm_data;
+
 	    user_nvdata_t user_data;
-	    usim_data_t usim_data;
 	    user_data_conf_t user_data_conf;
 
+	    usim_data_t usim_data;
+	    usim_data_conf_t usim_data_conf;
+
         sprintf(user, "%s%d", UE, i);
 
         ue_setting = config_setting_get_member(root_setting, user);
@@ -124,6 +120,11 @@ int parse_config_file(const char *output_dir, const char *conf_filename) {
             return EXIT_FAILURE;
         }
 
+        rc = parse_ue_plmn_param(ue_setting, i, &usim_data_conf.hplmn);
+        if (rc != EXIT_SUCCESS) {
+            return EXIT_FAILURE;
+        }
+
         rc = parse_ue_user_data(ue_setting, i, &user_data_conf);
         if (rc != EXIT_SUCCESS) {
             printf("Problem in USER section for UE%d. EXITING...\n", i);
@@ -132,21 +133,17 @@ int parse_config_file(const char *output_dir, const char *conf_filename) {
         gen_user_data(&user_data_conf, &user_data);
         write_user_data(output_dir, i, &user_data);
 
-        rc = parse_ue_sim_param(ue_setting, i);
+        rc = parse_ue_sim_param(ue_setting, i, &usim_data_conf);
         if (rc != EXIT_SUCCESS) {
             printf("Problem in SIM section for UE%d. EXITING...\n", i);
             return EXIT_FAILURE;
         }
+        gen_usim_data(&usim_data_conf, &usim_data);
+        write_usim_data(output_dir, i, &usim_data);
 
-        rc = parse_ue_plmn_param(ue_setting, i);
-        if (rc != EXIT_SUCCESS) {
-            return EXIT_FAILURE;
-        }
-        gen_emm_data(&emm_data);
+        gen_emm_data(&emm_data, usim_data_conf.hplmn, usim_data_conf.msin);
         write_emm_data(output_dir, i, &emm_data);
 
-        gen_usim_data(&usim_data);
-        write_usim_data(output_dir, i, &usim_data);
      }
     config_destroy(&cfg);
 	return(EXIT_SUCCESS);
@@ -172,264 +169,6 @@ int get_config_from_file(const char *filename, config_t *config) {
     return EXIT_SUCCESS;
 }
 
-void gen_usim_data(usim_data_t *usim_data) {
-	memset(usim_data, 0, sizeof(usim_data_t));
-	usim_data->imsi.length = 8;
-	usim_data->imsi.u.num.parity = get_msin_parity(msin);
-
-	usim_data->imsi.u.num.digit1 = user_plmn_list[hplmn_index].mcc[0];
-	usim_data->imsi.u.num.digit2 = user_plmn_list[hplmn_index].mcc[1];
-	usim_data->imsi.u.num.digit3 = user_plmn_list[hplmn_index].mcc[2];
-
-	usim_data->imsi.u.num.digit4 = user_plmn_list[hplmn_index].mnc[0];
-	usim_data->imsi.u.num.digit5 = user_plmn_list[hplmn_index].mnc[1];
-
-	if (strlen(user_plmn_list[hplmn_index].mnc) == 2) {
-		usim_data->imsi.u.num.digit6 = msin[0];
-		usim_data->imsi.u.num.digit7 = msin[1];
-		usim_data->imsi.u.num.digit8 = msin[2];
-		usim_data->imsi.u.num.digit9 = msin[3];
-		usim_data->imsi.u.num.digit10 = msin[4];
-		usim_data->imsi.u.num.digit11 = msin[5];
-		usim_data->imsi.u.num.digit12 = msin[6];
-		usim_data->imsi.u.num.digit13 = msin[7];
-		usim_data->imsi.u.num.digit14 = msin[8];
-		usim_data->imsi.u.num.digit15 = msin[9];
-	} else {
-		usim_data->imsi.u.num.digit6 = user_plmn_list[hplmn_index].mnc[2];
-		usim_data->imsi.u.num.digit7 = msin[0];
-		usim_data->imsi.u.num.digit8 = msin[1];
-		usim_data->imsi.u.num.digit9 = msin[2];
-		usim_data->imsi.u.num.digit10 = msin[3];
-		usim_data->imsi.u.num.digit11 = msin[4];
-		usim_data->imsi.u.num.digit12 = msin[5];
-		usim_data->imsi.u.num.digit13 = msin[6];
-		usim_data->imsi.u.num.digit14 = msin[7];
-		usim_data->imsi.u.num.digit15 = msin[8];
-	}
-
-	/*
-	 * Ciphering and Integrity Keys
-	 */
-	usim_data->keys.ksi = KSI;
-	memset(&usim_data->keys.ck, 0, USIM_CK_SIZE);
-	memset(&usim_data->keys.ik, 0, USIM_IK_SIZE);
-	/*
-	 * Higher Priority PLMN search period
-	 */
-	usim_data->hpplmn = 0x00; /* Disable timer */
-
-	/*
-	 * List of Forbidden PLMNs
-	 */
-	for (int i = 0; i < USIM_FPLMN_MAX; i++) {
-		memset(&usim_data->fplmn[i], 0xff, sizeof(plmn_t));
-	}
-	if (fplmn_nb > 0) {
-		for (int i = 0; i < fplmn_nb; i++) {
-			usim_data->fplmn[i] = user_network_record_list[fplmn[i]].plmn;
-		}
-	}
-
-	/*
-	 * Location Information
-	 */
-	usim_data->loci.tmsi = DEFAULT_TMSI;
-	usim_data->loci.lai.plmn = user_network_record_list[hplmn_index].plmn;
-	usim_data->loci.lai.lac = DEFAULT_LAC;
-	usim_data->loci.status = USIM_LOCI_NOT_UPDATED;
-	/*
-	 * Packet Switched Location Information
-	 */
-	usim_data->psloci.p_tmsi = DEFAULT_P_TMSI;
-	usim_data->psloci.signature[0] = 0x01;
-	usim_data->psloci.signature[1] = 0x02;
-	usim_data->psloci.signature[2] = 0x03;
-	usim_data->psloci.rai.plmn = user_network_record_list[hplmn_index].plmn;
-	usim_data->psloci.rai.lac = DEFAULT_LAC;
-	usim_data->psloci.rai.rac = DEFAULT_RAC;
-	usim_data->psloci.status = USIM_PSLOCI_NOT_UPDATED;
-	/*
-	 * Administrative Data
-	 */
-	usim_data->ad.UE_Operation_Mode = USIM_NORMAL_MODE;
-	usim_data->ad.Additional_Info = 0xffff;
-	usim_data->ad.MNC_Length = strlen(user_plmn_list[hplmn_index].mnc);
-	/*
-	 * EPS NAS security context
-	 */
-	usim_data->securityctx.length = 52;
-	usim_data->securityctx.KSIasme.type = USIM_KSI_ASME_TAG;
-	usim_data->securityctx.KSIasme.length = 1;
-	usim_data->securityctx.KSIasme.value[0] = KSI_ASME;
-	usim_data->securityctx.Kasme.type = USIM_K_ASME_TAG;
-	usim_data->securityctx.Kasme.length = USIM_K_ASME_SIZE;
-	memset(usim_data->securityctx.Kasme.value, 0,
-			usim_data->securityctx.Kasme.length);
-	usim_data->securityctx.ulNAScount.type = USIM_UL_NAS_COUNT_TAG;
-	usim_data->securityctx.ulNAScount.length = USIM_UL_NAS_COUNT_SIZE;
-	memset(usim_data->securityctx.ulNAScount.value, 0,
-			usim_data->securityctx.ulNAScount.length);
-	usim_data->securityctx.dlNAScount.type = USIM_DL_NAS_COUNT_TAG;
-	usim_data->securityctx.dlNAScount.length = USIM_DL_NAS_COUNT_SIZE;
-	memset(usim_data->securityctx.dlNAScount.value, 0,
-			usim_data->securityctx.dlNAScount.length);
-	usim_data->securityctx.algorithmID.type = USIM_INT_ENC_ALGORITHMS_TAG;
-	usim_data->securityctx.algorithmID.length = 1;
-	usim_data->securityctx.algorithmID.value[0] = SECURITY_ALGORITHMS;
-	/*
-	 * Subcriber's Number
-	 */
-	usim_data->msisdn.length = 7;
-	usim_data->msisdn.number.ext = 1;
-	usim_data->msisdn.number.ton = MSISDN_TON_UNKNOWKN;
-	usim_data->msisdn.number.npi = MSISDN_NPI_ISDN_TELEPHONY;
-	usim_data->msisdn.conf1_record_id = 0xff; /* Not used */
-	usim_data->msisdn.ext1_record_id = 0xff; /* Not used */
-	int j = 0;
-	for (int i = 0; i < strlen(msisdn); i += 2) {
-		usim_data->msisdn.number.digit[j].msb = msisdn[i];
-		j++;
-	}
-	j = 0;
-	for (int i = 1; i < strlen(msisdn); i += 2) {
-		usim_data->msisdn.number.digit[j].lsb = msisdn[i];
-		j++;
-
-	}
-	if (strlen(msisdn) % 2 == 0) {
-		for (int i = strlen(msisdn) / 2; i < 10; i++) {
-			usim_data->msisdn.number.digit[i].msb = 0xf;
-			usim_data->msisdn.number.digit[i].lsb = 0xf;
-		}
-	} else {
-		usim_data->msisdn.number.digit[strlen(msisdn) / 2].lsb = 0xf;
-		for (int i = (strlen(msisdn) / 2) + 1; i < 10; i++) {
-			usim_data->msisdn.number.digit[i].msb = 0xf;
-			usim_data->msisdn.number.digit[i].lsb = 0xf;
-		}
-	}
-	/*
-	 * PLMN Network Name and Operator PLMN List
-	 */
-	for (int i = 0; i < oplmn_nb; i++) {
-		network_record_t record = user_network_record_list[oplmn[i]];
-		usim_data->pnn[i].fullname.type = USIM_PNN_FULLNAME_TAG;
-		usim_data->pnn[i].fullname.length = strlen(record.fullname);
-		strncpy((char*) usim_data->pnn[i].fullname.value, record.fullname,
-				usim_data->pnn[i].fullname.length);
-		usim_data->pnn[i].shortname.type = USIM_PNN_SHORTNAME_TAG;
-		usim_data->pnn[i].shortname.length = strlen(record.shortname);
-		strncpy((char*) usim_data->pnn[i].shortname.value, record.shortname,
-				usim_data->pnn[i].shortname.length);
-		usim_data->opl[i].plmn = record.plmn;
-		usim_data->opl[i].start = record.tac_start;
-		usim_data->opl[i].end = record.tac_end;
-		usim_data->opl[i].record_id = i;
-	}
-	if (oplmn_nb < USIM_OPL_MAX) {
-		for (int i = oplmn_nb; i < USIM_OPL_MAX; i++) {
-			memset(&usim_data->opl[i].plmn, 0xff, sizeof(plmn_t));
-		}
-	}
-
-	/*
-	 * List of Equivalent HPLMNs
-	 */
-	for (int i = 0; i < ehplmn_nb; i++) {
-		usim_data->ehplmn[i] = user_network_record_list[ehplmn[i]].plmn;
-	}
-	if (ehplmn_nb < USIM_EHPLMN_MAX) {
-		for (int i = ehplmn_nb; i < USIM_EHPLMN_MAX; i++) {
-			memset(&usim_data->ehplmn[i], 0xff, sizeof(plmn_t));
-		}
-	}
-	/*
-	 * Home PLMN Selector with Access Technology
-	 */
-	usim_data->hplmn.plmn = user_network_record_list[hplmn_index].plmn;
-	usim_data->hplmn.AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN | USIM_ACT_EUTRAN);
-
-	/*
-	 * List of user controlled PLMN selector with Access Technology
-	 */
-	for (int i = 0; i < USIM_PLMN_MAX; i++) {
-		memset(&usim_data->plmn[i], 0xff, sizeof(plmn_t));
-	}
-	if (ucplmn_nb > 0) {
-		for (int i = 0; i < ucplmn_nb; i++) {
-			usim_data->plmn[i].plmn = user_network_record_list[ucplmn[i]].plmn;
-		}
-	}
-
-	// List of operator controlled PLMN selector with Access Technology
-
-	for (int i = 0; i < USIM_OPLMN_MAX; i++) {
-		memset(&usim_data->oplmn[i], 0xff, sizeof(plmn_t));
-	}
-	if (ocplmn_nb > 0) {
-		for (int i = 0; i < ocplmn_nb; i++) {
-			usim_data->oplmn[i].plmn = user_network_record_list[ocplmn[i]].plmn;
-			usim_data->oplmn[i].AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN
-					| USIM_ACT_EUTRAN);
-		}
-	}
-	/*
-	 * EPS Location Information
-	 */
-	usim_data->epsloci.guti.gummei.plmn =
-			user_network_record_list[hplmn_index].plmn;
-	usim_data->epsloci.guti.gummei.MMEgid = DEFAULT_MME_ID;
-	usim_data->epsloci.guti.gummei.MMEcode = DEFAULT_MME_CODE;
-	usim_data->epsloci.guti.m_tmsi = DEFAULT_M_TMSI;
-	usim_data->epsloci.tai.plmn = usim_data->epsloci.guti.gummei.plmn;
-	usim_data->epsloci.tai.tac = DEFAULT_TAC;
-	usim_data->epsloci.status = USIM_EPSLOCI_UPDATED;
-	/*
-	 * Non-Access Stratum configuration
-	 */
-	usim_data->nasconfig.NAS_SignallingPriority.type =
-	USIM_NAS_SIGNALLING_PRIORITY_TAG;
-	usim_data->nasconfig.NAS_SignallingPriority.length = 1;
-	usim_data->nasconfig.NAS_SignallingPriority.value[0] = 0x00;
-	usim_data->nasconfig.NMO_I_Behaviour.type = USIM_NMO_I_BEHAVIOUR_TAG;
-	usim_data->nasconfig.NMO_I_Behaviour.length = 1;
-	usim_data->nasconfig.NMO_I_Behaviour.value[0] = 0x00;
-	usim_data->nasconfig.AttachWithImsi.type = USIM_ATTACH_WITH_IMSI_TAG;
-	usim_data->nasconfig.AttachWithImsi.length = 1;
-#if defined(START_WITH_GUTI)
-	usim_data->nasconfig.AttachWithImsi.value[0] = 0x00;
-#else
-	usim_data->nasconfig.AttachWithImsi.value[0] = 0x01;
-#endif
-	usim_data->nasconfig.MinimumPeriodicSearchTimer.type =
-	USIM_MINIMUM_PERIODIC_SEARCH_TIMER_TAG;
-	usim_data->nasconfig.MinimumPeriodicSearchTimer.length = 1;
-	usim_data->nasconfig.MinimumPeriodicSearchTimer.value[0] = 0x00;
-	usim_data->nasconfig.ExtendedAccessBarring.type =
-	USIM_EXTENDED_ACCESS_BARRING_TAG;
-	usim_data->nasconfig.ExtendedAccessBarring.length = 1;
-	usim_data->nasconfig.ExtendedAccessBarring.value[0] = 0x00;
-	usim_data->nasconfig.Timer_T3245_Behaviour.type =
-	USIM_TIMER_T3245_BEHAVIOUR_TAG;
-	usim_data->nasconfig.Timer_T3245_Behaviour.length = 1;
-	usim_data->nasconfig.Timer_T3245_Behaviour.value[0] = 0x00;
-
-	/* initialize the subscriber authentication security key */
-	hex_string_to_hex_value(usim_data->keys.usim_api_k,
-			usim_api_k, USIM_API_K_SIZE);
-	hex_string_to_hex_value(usim_data->keys.opc, opc,
-	OPC_SIZE);
-}
-
-int write_usim_data(const char *directory, int user_id, usim_data_t *usim_data){
-    int rc;
-    char *filename = make_filename(directory, USIM_API_NVRAM_FILENAME, user_id);
-    rc = usim_api_write(filename, usim_data);
-    free(filename);
-    return rc;
-}
-
 
 int parse_plmn_param(config_setting_t *plmn_setting, int index) {
 	int rc = 0;
@@ -488,14 +227,17 @@ int parse_plmns(config_setting_t *all_plmn_setting) {
 	return rc;
 }
 
-int parse_ue_plmn_param(config_setting_t *ue_setting, int user_id) {
+int parse_ue_plmn_param(config_setting_t *ue_setting, int user_id, const char **h) {
 	int rc = EXIT_SUCCESS;
+	const char *hplmn;
 	config_setting_t *setting = NULL;
-	rc = config_setting_lookup_string(ue_setting, HPLMN, &hplmn);
+	rc = config_setting_lookup_string(ue_setting, HPLMN, h);
 	if (rc != 1) {
 		printf("Check HPLMN section for UE%d. Exiting\n", user_id);
 		return EXIT_FAILURE;
-	} else if (get_plmn_index(hplmn) == -1) {
+	}
+	hplmn = *h;
+	if (get_plmn_index(hplmn) == -1) {
 		printf("HPLMN for UE%d is not defined in PLMN section. Exiting\n",
 				user_id);
 		return EXIT_FAILURE;
@@ -553,39 +295,6 @@ int parse_ue_plmn_param(config_setting_t *ue_setting, int user_id) {
 	return EXIT_SUCCESS;
 }
 
-int parse_ue_sim_param(config_setting_t *ue_setting, int user_id) {
-	int rc = EXIT_SUCCESS;
-	config_setting_t *ue_param_setting = NULL;
-	ue_param_setting = config_setting_get_member(ue_setting, SIM);
-	if (ue_param_setting == NULL) {
-		printf("Check SIM section for UE%d. EXITING...\n", user_id);
-		return EXIT_FAILURE;
-	}
-	rc = config_setting_lookup_string(ue_param_setting, MSIN, &msin);
-	if (rc != 1 || strlen(msin) > 10 || strlen(msin) < 9) {
-		printf("Check SIM MSIN section for UE%d. Exiting\n", user_id);
-		return EXIT_FAILURE;
-	}
-	rc = config_setting_lookup_string(ue_param_setting, USIM_API_K,
-			&usim_api_k);
-	if (rc != 1) {
-		printf("Check SIM USIM_API_K  section for UE%d. Exiting\n", user_id);
-		return EXIT_FAILURE;
-	}
-	rc = config_setting_lookup_string(ue_param_setting, OPC, &opc);
-	if (rc != 1) {
-		printf("Check SIM OPC section for UE%d. Exiting\n", user_id);
-		return EXIT_FAILURE;
-	}
-	rc = config_setting_lookup_string(ue_param_setting, MSISDN, &msisdn);
-	if (rc != 1) {
-		printf("Check SIM MSISDN section for UE%d. Exiting\n", user_id);
-		return EXIT_FAILURE;
-	}
-	return EXIT_SUCCESS;
-}
-
-
 int fill_ucplmn(config_setting_t* setting, int user_id) {
 	int rc;
 	ucplmn_nb = config_setting_length(setting);
diff --git a/openair3/NAS/TOOLS/conf2uedata.h b/openair3/NAS/TOOLS/conf2uedata.h
index cb2b31a4ff5..7ae326bf1c4 100644
--- a/openair3/NAS/TOOLS/conf2uedata.h
+++ b/openair3/NAS/TOOLS/conf2uedata.h
@@ -6,7 +6,7 @@
 #include "usim_api.h"
 
 #define UE "UE"
-#define SIM "SIM"
+
 #define PLMN "PLMN"
 
 #define FULLNAME "FULLNAME"
@@ -14,16 +14,6 @@
 #define MNC "MNC"
 #define MCC "MCC"
 
-#define MSIN "MSIN"
-#define USIM_API_K "USIM_API_K"
-#define OPC "OPC"
-#define MSISDN "MSISDN"
-
-#define UE_IMEI "IMEI"
-#define MANUFACTURER "MANUFACTURER"
-#define MODEL "MODEL"
-#define PINCODE "PIN"
-
 #define HPLMN "HPLMN"
 #define UCPLMN "UCPLMN_LIST"
 #define OPLMN "OPLMN_LIST"
@@ -31,26 +21,9 @@
 #define FPLMN "FPLMN_LIST"
 #define EHPLMN "EHPLMN_LIST"
 
-#define KSI     USIM_KSI_NOT_AVAILABLE
-
-#define KSI_ASME    USIM_KSI_NOT_AVAILABLE
-#define INT_ALGO    USIM_INT_EIA1
-#define ENC_ALGO    USIM_ENC_EEA0
-#define SECURITY_ALGORITHMS (ENC_ALGO | INT_ALGO)
-#define OPC_SIZE	16
 #define MIN_TAC     0x0000
 #define MAX_TAC     0xFFFE
 
-#define DEFAULT_TMSI    0x0000000D
-#define DEFAULT_P_TMSI    0x0000000D
-#define DEFAULT_M_TMSI    0x0000000D
-#define DEFAULT_LAC   0xFFFE
-#define DEFAULT_RAC   0x01
-#define DEFAULT_TAC   0x0001
-
-#define DEFAULT_MME_ID    0x0102
-#define DEFAULT_MME_CODE  0x0F
-
 /*
  * PLMN network operator record
  */
@@ -70,12 +43,6 @@ typedef struct {
 	const char *mcc;
 } plmn_conf_param_t;
 
-extern const char *msin;
-extern const char *usim_api_k;
-extern const char *msisdn;
-extern const char *opc;
-extern const char *hplmn;
-
 extern int *ucplmn;
 extern int *oplmn;
 extern int *ocplmn;
@@ -99,14 +66,10 @@ int parse_config_file(const char *output_dir, const char *filename);
 void _display_usage(void);
 void fill_network_record_list(void);
 
-int write_usim_data(const char *directory, int user_id, usim_data_t *usim_data);
-void gen_usim_data(usim_data_t *usim_data);
-
-int parse_ue_sim_param(config_setting_t *ue_setting, int user_id);
 int parse_plmn_param(config_setting_t *plmn_setting, int index);
 int parse_plmns(config_setting_t *all_plmn_setting);
 int get_plmn_index(const char * mccmnc);
-int parse_ue_plmn_param(config_setting_t *ue_setting, int user_id);
+int parse_ue_plmn_param(config_setting_t *ue_setting, int user_id, const char **hplmn);
 int fill_ucplmn(config_setting_t* setting, int use_id);
 int fill_oplmn(config_setting_t* setting, int use_id);
 int fill_ocplmn(config_setting_t* setting, int use_id);
diff --git a/openair3/NAS/TOOLS/conf_emm.c b/openair3/NAS/TOOLS/conf_emm.c
index a46fc5d59b4..ad877e32efc 100644
--- a/openair3/NAS/TOOLS/conf_emm.c
+++ b/openair3/NAS/TOOLS/conf_emm.c
@@ -5,7 +5,7 @@
 #include "conf_emm.h"
 #include "fs.h"
 
-void gen_emm_data(emm_nvdata_t *emm_data) {
+void gen_emm_data(emm_nvdata_t *emm_data, const char *hplmn, const char *msin) {
 	hplmn_index = get_plmn_index(hplmn);
 	memset(emm_data, 0, sizeof(emm_nvdata_t));
 	int hplmn_index = get_plmn_index(hplmn);
diff --git a/openair3/NAS/TOOLS/conf_emm.h b/openair3/NAS/TOOLS/conf_emm.h
index ddb920f5b50..80562aba554 100644
--- a/openair3/NAS/TOOLS/conf_emm.h
+++ b/openair3/NAS/TOOLS/conf_emm.h
@@ -3,7 +3,7 @@
 
 #include "emmData.h"
 
-void gen_emm_data(emm_nvdata_t *emm_data);
+void gen_emm_data(emm_nvdata_t *emm_data, const char *hplmn, const char *msin);
 int write_emm_data(const char *directory, int user_id, emm_nvdata_t *emm_data);
 int get_msin_parity(const char * msin);
 
diff --git a/openair3/NAS/TOOLS/conf_usim.c b/openair3/NAS/TOOLS/conf_usim.c
new file mode 100644
index 00000000000..ee8ed8e0d0b
--- /dev/null
+++ b/openair3/NAS/TOOLS/conf_usim.c
@@ -0,0 +1,301 @@
+#include <string.h>
+#include <stdlib.h>
+
+#include "userDef.h"
+#include "utils.h"
+#include "conf_emm.h"
+#include "fs.h"
+#include "conf_usim.h"
+#include "conf2uedata.h"
+
+int parse_ue_sim_param(config_setting_t *ue_setting, int user_id, usim_data_conf_t *u) {
+	int rc = EXIT_SUCCESS;
+	config_setting_t *ue_param_setting = NULL;
+	ue_param_setting = config_setting_get_member(ue_setting, SIM);
+	if (ue_param_setting == NULL) {
+		printf("Check SIM section for UE%d. EXITING...\n", user_id);
+		return EXIT_FAILURE;
+	}
+	rc = config_setting_lookup_string(ue_param_setting, MSIN, &u->msin);
+	if (rc != 1 || strlen(u->msin) > 10 || strlen(u->msin) < 9) {
+		printf("Check SIM MSIN section for UE%d. Exiting\n", user_id);
+		return EXIT_FAILURE;
+	}
+	rc = config_setting_lookup_string(ue_param_setting, USIM_API_K,
+			&u->usim_api_k);
+	if (rc != 1) {
+		printf("Check SIM USIM_API_K  section for UE%d. Exiting\n", user_id);
+		return EXIT_FAILURE;
+	}
+	rc = config_setting_lookup_string(ue_param_setting, OPC, &u->opc);
+	if (rc != 1) {
+		printf("Check SIM OPC section for UE%d. Exiting\n", user_id);
+		return EXIT_FAILURE;
+	}
+	rc = config_setting_lookup_string(ue_param_setting, MSISDN, &u->msisdn);
+	if (rc != 1) {
+		printf("Check SIM MSISDN section for UE%d. Exiting\n", user_id);
+		return EXIT_FAILURE;
+	}
+	return EXIT_SUCCESS;
+}
+
+void gen_usim_data(usim_data_conf_t *u, usim_data_t *usim_data) {
+	memset(usim_data, 0, sizeof(usim_data_t));
+	usim_data->imsi.length = 8;
+	usim_data->imsi.u.num.parity = get_msin_parity(u->msin);
+
+	usim_data->imsi.u.num.digit1 = user_plmn_list[hplmn_index].mcc[0];
+	usim_data->imsi.u.num.digit2 = user_plmn_list[hplmn_index].mcc[1];
+	usim_data->imsi.u.num.digit3 = user_plmn_list[hplmn_index].mcc[2];
+
+	usim_data->imsi.u.num.digit4 = user_plmn_list[hplmn_index].mnc[0];
+	usim_data->imsi.u.num.digit5 = user_plmn_list[hplmn_index].mnc[1];
+
+	if (strlen(user_plmn_list[hplmn_index].mnc) == 2) {
+		usim_data->imsi.u.num.digit6 = u->msin[0];
+		usim_data->imsi.u.num.digit7 = u->msin[1];
+		usim_data->imsi.u.num.digit8 = u->msin[2];
+		usim_data->imsi.u.num.digit9 = u->msin[3];
+		usim_data->imsi.u.num.digit10 = u->msin[4];
+		usim_data->imsi.u.num.digit11 = u->msin[5];
+		usim_data->imsi.u.num.digit12 = u->msin[6];
+		usim_data->imsi.u.num.digit13 = u->msin[7];
+		usim_data->imsi.u.num.digit14 = u->msin[8];
+		usim_data->imsi.u.num.digit15 = u->msin[9];
+	} else {
+		usim_data->imsi.u.num.digit6 = user_plmn_list[hplmn_index].mnc[2];
+		usim_data->imsi.u.num.digit7 = u->msin[0];
+		usim_data->imsi.u.num.digit8 = u->msin[1];
+		usim_data->imsi.u.num.digit9 = u->msin[2];
+		usim_data->imsi.u.num.digit10 = u->msin[3];
+		usim_data->imsi.u.num.digit11 = u->msin[4];
+		usim_data->imsi.u.num.digit12 = u->msin[5];
+		usim_data->imsi.u.num.digit13 = u->msin[6];
+		usim_data->imsi.u.num.digit14 = u->msin[7];
+		usim_data->imsi.u.num.digit15 = u->msin[8];
+	}
+
+	/*
+	 * Ciphering and Integrity Keys
+	 */
+	usim_data->keys.ksi = KSI;
+	memset(&usim_data->keys.ck, 0, USIM_CK_SIZE);
+	memset(&usim_data->keys.ik, 0, USIM_IK_SIZE);
+	/*
+	 * Higher Priority PLMN search period
+	 */
+	usim_data->hpplmn = 0x00; /* Disable timer */
+
+	/*
+	 * List of Forbidden PLMNs
+	 */
+	for (int i = 0; i < USIM_FPLMN_MAX; i++) {
+		memset(&usim_data->fplmn[i], 0xff, sizeof(plmn_t));
+	}
+	if (fplmn_nb > 0) {
+		for (int i = 0; i < fplmn_nb; i++) {
+			usim_data->fplmn[i] = user_network_record_list[fplmn[i]].plmn;
+		}
+	}
+
+	/*
+	 * Location Information
+	 */
+	usim_data->loci.tmsi = DEFAULT_TMSI;
+	usim_data->loci.lai.plmn = user_network_record_list[hplmn_index].plmn;
+	usim_data->loci.lai.lac = DEFAULT_LAC;
+	usim_data->loci.status = USIM_LOCI_NOT_UPDATED;
+	/*
+	 * Packet Switched Location Information
+	 */
+	usim_data->psloci.p_tmsi = DEFAULT_P_TMSI;
+	usim_data->psloci.signature[0] = 0x01;
+	usim_data->psloci.signature[1] = 0x02;
+	usim_data->psloci.signature[2] = 0x03;
+	usim_data->psloci.rai.plmn = user_network_record_list[hplmn_index].plmn;
+	usim_data->psloci.rai.lac = DEFAULT_LAC;
+	usim_data->psloci.rai.rac = DEFAULT_RAC;
+	usim_data->psloci.status = USIM_PSLOCI_NOT_UPDATED;
+	/*
+	 * Administrative Data
+	 */
+	usim_data->ad.UE_Operation_Mode = USIM_NORMAL_MODE;
+	usim_data->ad.Additional_Info = 0xffff;
+	usim_data->ad.MNC_Length = strlen(user_plmn_list[hplmn_index].mnc);
+	/*
+	 * EPS NAS security context
+	 */
+	usim_data->securityctx.length = 52;
+	usim_data->securityctx.KSIasme.type = USIM_KSI_ASME_TAG;
+	usim_data->securityctx.KSIasme.length = 1;
+	usim_data->securityctx.KSIasme.value[0] = KSI_ASME;
+	usim_data->securityctx.Kasme.type = USIM_K_ASME_TAG;
+	usim_data->securityctx.Kasme.length = USIM_K_ASME_SIZE;
+	memset(usim_data->securityctx.Kasme.value, 0,
+			usim_data->securityctx.Kasme.length);
+	usim_data->securityctx.ulNAScount.type = USIM_UL_NAS_COUNT_TAG;
+	usim_data->securityctx.ulNAScount.length = USIM_UL_NAS_COUNT_SIZE;
+	memset(usim_data->securityctx.ulNAScount.value, 0,
+			usim_data->securityctx.ulNAScount.length);
+	usim_data->securityctx.dlNAScount.type = USIM_DL_NAS_COUNT_TAG;
+	usim_data->securityctx.dlNAScount.length = USIM_DL_NAS_COUNT_SIZE;
+	memset(usim_data->securityctx.dlNAScount.value, 0,
+			usim_data->securityctx.dlNAScount.length);
+	usim_data->securityctx.algorithmID.type = USIM_INT_ENC_ALGORITHMS_TAG;
+	usim_data->securityctx.algorithmID.length = 1;
+	usim_data->securityctx.algorithmID.value[0] = SECURITY_ALGORITHMS;
+	/*
+	 * Subcriber's Number
+	 */
+	usim_data->msisdn.length = 7;
+	usim_data->msisdn.number.ext = 1;
+	usim_data->msisdn.number.ton = MSISDN_TON_UNKNOWKN;
+	usim_data->msisdn.number.npi = MSISDN_NPI_ISDN_TELEPHONY;
+	usim_data->msisdn.conf1_record_id = 0xff; /* Not used */
+	usim_data->msisdn.ext1_record_id = 0xff; /* Not used */
+	int j = 0;
+	for (int i = 0; i < strlen(u->msisdn); i += 2) {
+		usim_data->msisdn.number.digit[j].msb = u->msisdn[i];
+		j++;
+	}
+	j = 0;
+	for (int i = 1; i < strlen(u->msisdn); i += 2) {
+		usim_data->msisdn.number.digit[j].lsb = u->msisdn[i];
+		j++;
+
+	}
+	if (strlen(u->msisdn) % 2 == 0) {
+		for (int i = strlen(u->msisdn) / 2; i < 10; i++) {
+			usim_data->msisdn.number.digit[i].msb = 0xf;
+			usim_data->msisdn.number.digit[i].lsb = 0xf;
+		}
+	} else {
+		usim_data->msisdn.number.digit[strlen(u->msisdn) / 2].lsb = 0xf;
+		for (int i = (strlen(u->msisdn) / 2) + 1; i < 10; i++) {
+			usim_data->msisdn.number.digit[i].msb = 0xf;
+			usim_data->msisdn.number.digit[i].lsb = 0xf;
+		}
+	}
+	/*
+	 * PLMN Network Name and Operator PLMN List
+	 */
+	for (int i = 0; i < oplmn_nb; i++) {
+		network_record_t record = user_network_record_list[oplmn[i]];
+		usim_data->pnn[i].fullname.type = USIM_PNN_FULLNAME_TAG;
+		usim_data->pnn[i].fullname.length = strlen(record.fullname);
+		strncpy((char*) usim_data->pnn[i].fullname.value, record.fullname,
+				usim_data->pnn[i].fullname.length);
+		usim_data->pnn[i].shortname.type = USIM_PNN_SHORTNAME_TAG;
+		usim_data->pnn[i].shortname.length = strlen(record.shortname);
+		strncpy((char*) usim_data->pnn[i].shortname.value, record.shortname,
+				usim_data->pnn[i].shortname.length);
+		usim_data->opl[i].plmn = record.plmn;
+		usim_data->opl[i].start = record.tac_start;
+		usim_data->opl[i].end = record.tac_end;
+		usim_data->opl[i].record_id = i;
+	}
+	if (oplmn_nb < USIM_OPL_MAX) {
+		for (int i = oplmn_nb; i < USIM_OPL_MAX; i++) {
+			memset(&usim_data->opl[i].plmn, 0xff, sizeof(plmn_t));
+		}
+	}
+
+	/*
+	 * List of Equivalent HPLMNs
+	 */
+	for (int i = 0; i < ehplmn_nb; i++) {
+		usim_data->ehplmn[i] = user_network_record_list[ehplmn[i]].plmn;
+	}
+	if (ehplmn_nb < USIM_EHPLMN_MAX) {
+		for (int i = ehplmn_nb; i < USIM_EHPLMN_MAX; i++) {
+			memset(&usim_data->ehplmn[i], 0xff, sizeof(plmn_t));
+		}
+	}
+	/*
+	 * Home PLMN Selector with Access Technology
+	 */
+	usim_data->hplmn.plmn = user_network_record_list[hplmn_index].plmn;
+	usim_data->hplmn.AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN | USIM_ACT_EUTRAN);
+
+	/*
+	 * List of user controlled PLMN selector with Access Technology
+	 */
+	for (int i = 0; i < USIM_PLMN_MAX; i++) {
+		memset(&usim_data->plmn[i], 0xff, sizeof(plmn_t));
+	}
+	if (ucplmn_nb > 0) {
+		for (int i = 0; i < ucplmn_nb; i++) {
+			usim_data->plmn[i].plmn = user_network_record_list[ucplmn[i]].plmn;
+		}
+	}
+
+	// List of operator controlled PLMN selector with Access Technology
+
+	for (int i = 0; i < USIM_OPLMN_MAX; i++) {
+		memset(&usim_data->oplmn[i], 0xff, sizeof(plmn_t));
+	}
+	if (ocplmn_nb > 0) {
+		for (int i = 0; i < ocplmn_nb; i++) {
+			usim_data->oplmn[i].plmn = user_network_record_list[ocplmn[i]].plmn;
+			usim_data->oplmn[i].AcT = (USIM_ACT_GSM | USIM_ACT_UTRAN
+					| USIM_ACT_EUTRAN);
+		}
+	}
+	/*
+	 * EPS Location Information
+	 */
+	usim_data->epsloci.guti.gummei.plmn =
+			user_network_record_list[hplmn_index].plmn;
+	usim_data->epsloci.guti.gummei.MMEgid = DEFAULT_MME_ID;
+	usim_data->epsloci.guti.gummei.MMEcode = DEFAULT_MME_CODE;
+	usim_data->epsloci.guti.m_tmsi = DEFAULT_M_TMSI;
+	usim_data->epsloci.tai.plmn = usim_data->epsloci.guti.gummei.plmn;
+	usim_data->epsloci.tai.tac = DEFAULT_TAC;
+	usim_data->epsloci.status = USIM_EPSLOCI_UPDATED;
+	/*
+	 * Non-Access Stratum configuration
+	 */
+	usim_data->nasconfig.NAS_SignallingPriority.type =
+	USIM_NAS_SIGNALLING_PRIORITY_TAG;
+	usim_data->nasconfig.NAS_SignallingPriority.length = 1;
+	usim_data->nasconfig.NAS_SignallingPriority.value[0] = 0x00;
+	usim_data->nasconfig.NMO_I_Behaviour.type = USIM_NMO_I_BEHAVIOUR_TAG;
+	usim_data->nasconfig.NMO_I_Behaviour.length = 1;
+	usim_data->nasconfig.NMO_I_Behaviour.value[0] = 0x00;
+	usim_data->nasconfig.AttachWithImsi.type = USIM_ATTACH_WITH_IMSI_TAG;
+	usim_data->nasconfig.AttachWithImsi.length = 1;
+#if defined(START_WITH_GUTI)
+	usim_data->nasconfig.AttachWithImsi.value[0] = 0x00;
+#else
+	usim_data->nasconfig.AttachWithImsi.value[0] = 0x01;
+#endif
+	usim_data->nasconfig.MinimumPeriodicSearchTimer.type =
+	USIM_MINIMUM_PERIODIC_SEARCH_TIMER_TAG;
+	usim_data->nasconfig.MinimumPeriodicSearchTimer.length = 1;
+	usim_data->nasconfig.MinimumPeriodicSearchTimer.value[0] = 0x00;
+	usim_data->nasconfig.ExtendedAccessBarring.type =
+	USIM_EXTENDED_ACCESS_BARRING_TAG;
+	usim_data->nasconfig.ExtendedAccessBarring.length = 1;
+	usim_data->nasconfig.ExtendedAccessBarring.value[0] = 0x00;
+	usim_data->nasconfig.Timer_T3245_Behaviour.type =
+	USIM_TIMER_T3245_BEHAVIOUR_TAG;
+	usim_data->nasconfig.Timer_T3245_Behaviour.length = 1;
+	usim_data->nasconfig.Timer_T3245_Behaviour.value[0] = 0x00;
+
+	/* initialize the subscriber authentication security key */
+	hex_string_to_hex_value(usim_data->keys.usim_api_k,
+			u->usim_api_k, USIM_API_K_SIZE);
+	hex_string_to_hex_value(usim_data->keys.opc, u->opc,
+	OPC_SIZE);
+}
+
+int write_usim_data(const char *directory, int user_id, usim_data_t *usim_data){
+    int rc;
+    char *filename = make_filename(directory, USIM_API_NVRAM_FILENAME, user_id);
+    rc = usim_api_write(filename, usim_data);
+    free(filename);
+    return rc;
+}
+
+
diff --git a/openair3/NAS/TOOLS/conf_usim.h b/openair3/NAS/TOOLS/conf_usim.h
new file mode 100644
index 00000000000..3375bf9d5d5
--- /dev/null
+++ b/openair3/NAS/TOOLS/conf_usim.h
@@ -0,0 +1,45 @@
+#ifndef _CONF_USIM_H
+#define _CONF_USIM_H
+
+#include <libconfig.h>
+#include "usim_api.h"
+
+#define SIM "SIM"
+#define MSIN "MSIN"
+#define USIM_API_K "USIM_API_K"
+#define OPC "OPC"
+#define MSISDN "MSISDN"
+
+#define KSI               USIM_KSI_NOT_AVAILABLE
+#define KSI_ASME          USIM_KSI_NOT_AVAILABLE
+
+#define OPC_SIZE          16
+
+#define DEFAULT_TMSI      0x0000000D
+#define DEFAULT_P_TMSI    0x0000000D
+#define DEFAULT_M_TMSI    0x0000000D
+
+#define DEFAULT_RAC       0x01
+#define DEFAULT_TAC       0x0001
+#define DEFAULT_LAC       0xFFFE
+
+#define DEFAULT_MME_ID    0x0102
+#define DEFAULT_MME_CODE  0x0F
+
+#define INT_ALGO          USIM_INT_EIA1
+#define ENC_ALGO          USIM_ENC_EEA0
+#define SECURITY_ALGORITHMS (ENC_ALGO | INT_ALGO)
+
+typedef struct {
+    const char *msin;
+    const char *usim_api_k;
+    const char *msisdn;
+    const char *opc;
+    const char *hplmn;
+} usim_data_conf_t;
+
+int parse_ue_sim_param(config_setting_t *ue_setting, int user_id, usim_data_conf_t *u);
+int write_usim_data(const char *directory, int user_id, usim_data_t *usim_data);
+void gen_usim_data(usim_data_conf_t *u, usim_data_t *usim_data);
+
+#endif
-- 
GitLab