Commit 212192cb authored by Cedric Roux's avatar Cedric Roux

- Added new feature: Oaisim Security Algorithms (see README in openair2/UTIL/OSA/README

- Fix uint64_t formatting in openair_proc.c
- Removed duplicate call to pdcp_fifo_read_input_sdus

pre-ci tests passed

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4158 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent 15e4d364
......@@ -26,6 +26,7 @@ SOURCES_L2 += $(PDCP_DIR)/pdcp_fifo.c
SOURCES_L2 += $(PDCP_DIR)/pdcp_sequence_manager.c
SOURCES_L2 += $(PDCP_DIR)/pdcp_primitives.c
SOURCES_L2 += $(PDCP_DIR)/pdcp_util.c
SOURCES_L2 += $(PDCP_DIR)/pdcp_security.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am.c
SOURCES_L2 += $(RLC_AM_DIR)/rlc_am_init.c
......
This diff is collapsed.
......@@ -110,9 +110,26 @@ typedef struct pdcp_t {
BOOL instanciated_instance;
u16 header_compression_profile;
/* SR: added this flag to distinguish UE/eNB instance as pdcp_run for virtual
* mode can receive data on NETLINK for eNB while eNB_flag = 0 and for UE when eNB_flag = 1
*/
u8 is_ue;
/* Configured security algorithms */
u8 cipheringAlgorithm;
u8 integrityProtAlgorithm;
/* User-Plane encryption key
* Control-Plane RRC encryption key
* Control-Plane RRC integrity key
* These keys are configured by RRC layer
*/
u8 *kUPenc;
u8 *kRRCint;
u8 *kRRCenc;
u8 security_activated;
u8 rlc_mode;
u8 status_report;
u8 seq_num_size;
......@@ -260,14 +277,25 @@ public_pdcp(void rrc_pdcp_config_req (module_id_t module_id, u32 frame, u8_t eNB
* \param[in] srb2add_list SRB configuration list to be created.
* \param[in] drb2add_list DRB configuration list to be created.
* \param[in] drb2release_list DRB configuration list to be released.
* \param[in] security_mode Security algorithm to apply for integrity/ciphering
* \param[in] kRRCenc RRC encryption key
* \param[in] kRRCint RRC integrity key
* \param[in] kUPenc User-Plane encryption key
* \return A status about the processing, OK or error code.
*/
public_pdcp(
BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u8_t eNB_flag, u32_t index,
SRB_ToAddModList_t* srb2add_list,
DRB_ToAddModList_t* drb2add_list,
DRB_ToReleaseList_t* drb2release_list,
u8 security_mode,
u8 *kRRCenc,
u8 *kRRCint,
u8 *kUPenc
#ifdef Rel10
public_pdcp(BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u8_t eNB_flag, u32_t index, SRB_ToAddModList_t* srb2add_list, DRB_ToAddModList_t* drb2add_list, DRB_ToReleaseList_t* drb2release_list,PMCH_InfoList_r9_t* pmch_InfoList_r9);)
#else
public_pdcp(BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u8_t eNB_flag, u32_t index, SRB_ToAddModList_t* srb2add_list, DRB_ToAddModList_t* drb2add_list, DRB_ToReleaseList_t* drb2release_list);)
,PMCH_InfoList_r9_t* pmch_InfoList_r9
#endif
));
/*! \fn BOOL pdcp_config_req_asn1 (module_id_t module_id, u32 frame, u8_t eNB_flag, u32 action, rb_id_t rb_id, u8 rb_sn, u8 rb_report, u16 header_compression_profile, u8 security_mode)
* \brief Function for RRC to configure a Radio Bearer.
......@@ -280,10 +308,18 @@ public_pdcp(BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u
* \param[in] drb_report set a pdcp report for this drb
* \param[in] header_compression set the rohc profile
* \param[in] security_mode set the integrity and ciphering algs
* \param[in] kRRCenc RRC encryption key
* \param[in] kRRCint RRC integrity key
* \param[in] kUPenc User-Plane encryption key
* \return A status about the processing, OK or error code.
*/
public_pdcp(BOOL pdcp_config_req_asn1 (module_id_t module_id, u32 frame, u8_t eNB_flag, u16 index, rlc_mode_t rlc_mode, u32 action, u16 lc_id, u16 mch_id, rb_id_t rb_id, u8 rb_sn, u8 rb_report, u16 header_compression_profile, u8 security_mode);)
public_pdcp(BOOL pdcp_config_req_asn1 (module_id_t module_id, u32 frame, u8_t eNB_flag, u16 index,
rlc_mode_t rlc_mode, u32 action, u16 lc_id,u16 mch_id, rb_id_t rb_id,
u8 rb_sn, u8 rb_report, u16 header_compression_profile,
u8 security_mode,
u8 *kRRCenc,
u8 *kRRCint,
u8 *kUPenc));
/*! \fn void rrc_pdcp_config_release(module_id_t, rb_id_t)
* \brief This functions is unused
* \param[in] module_id Module ID of relevant PDCP entity
......
......@@ -153,4 +153,17 @@ BOOL pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer(unsigned char* pdu_b
BOOL pdcp_serialize_control_pdu_for_pdcp_status_report(unsigned char* pdu_buffer, \
u8 bitmap[512], pdcp_control_pdu_for_pdcp_status_report* pdu);
void pdcp_config_set_security(module_id_t module_id, u32 frame, u8 eNB_flag, rb_id_t rb_id,
u16 lc_id, u8 security_mode, u8 *kRRCenc, u8 *kRRCint, u8 *kUPenc);
#if defined(ENABLE_SECURITY)
int pdcp_apply_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
u8 pdcp_header_len, u16 current_sn, u8 *pdcp_pdu_buffer,
u16 sdu_buffer_size);
int pdcp_validate_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
u8 pdcp_header_len, u16 current_sn, u8 *pdcp_pdu_buffer,
u16 sdu_buffer_size);
#endif /* defined(ENABLE_SECURITY) */
#endif
/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fsr/openairinterface
Address : Eurecom, 2229, route des crêtes, 06560 Valbonne Sophia Antipolis, France
*******************************************************************************/
/*! \file pdcp_security.c
* \brief PDCP Security Methods
* \author ROUX Sebastien
* \date 2013
*/
#include <stdint.h>
#include "assertions.h"
#include "UTIL/LOG/log.h"
#include "UTIL/OSA/osa_defs.h"
#include "LAYER2/MAC/extern.h"
#include "pdcp.h"
#include "pdcp_primitives.h"
#if defined(ENABLE_SECURITY)
static
u32 pdcp_get_next_count_tx(pdcp_t *pdcp_entity, u8 pdcp_header_len, u16 pdcp_sn);
static
u32 pdcp_get_next_count_rx(pdcp_t *pdcp_entity, u8 pdcp_header_len, u16 pdcp_sn);
static
u32 pdcp_get_next_count_tx(pdcp_t *pdcp_entity, u8 pdcp_header_len, u16 pdcp_sn)
{
u32 count;
/* For TX COUNT = TX_HFN << length of SN | pdcp SN */
if (pdcp_header_len == PDCP_CONTROL_PLANE_DATA_PDU_SN_SIZE) {
/* 5 bits length SN */
count = (pdcp_entity->tx_hfn << 5) | (pdcp_sn & 0x001F);
} else {
/* 12 bits length SN */
count = (pdcp_entity->tx_hfn << 12) | (pdcp_sn & 0x0FFF);
}
// LOG_D(PDCP, "[OSA] TX COUNT = 0x%08x\n", count);
return count;
}
static
u32 pdcp_get_next_count_rx(pdcp_t *pdcp_entity, u8 pdcp_header_len, u16 pdcp_sn)
{
u32 count;
/* For RX COUNT = RX_HFN << length of SN | pdcp SN of received PDU */
if (pdcp_header_len == PDCP_CONTROL_PLANE_DATA_PDU_SN_SIZE) {
/* 5 bits length SN */
count = (pdcp_entity->rx_hfn << 5) | (pdcp_sn & 0x001F);
} else {
/* 12 bits length SN */
count = (pdcp_entity->rx_hfn << 12) | (pdcp_sn & 0x0FFF);
}
// LOG_D(PDCP, "[OSA] RX COUNT = 0x%08x\n", count);
return count;
}
int pdcp_apply_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
u8 pdcp_header_len, u16 current_sn, u8 *pdcp_pdu_buffer,
u16 sdu_buffer_size)
{
u8 *buffer_encrypted = NULL;
stream_cipher_t encrypt_params;
DevAssert(pdcp_entity != NULL);
DevAssert(pdcp_pdu_buffer != NULL);
DevCheck(rb_id < NB_RB_MAX && rb_id >= 0, rb_id, NB_RB_MAX, 0);
encrypt_params.direction = (pdcp_entity->is_ue == 1) ? SECU_DIRECTION_UPLINK : SECU_DIRECTION_DOWNLINK;
encrypt_params.bearer = rb_id;
encrypt_params.count = pdcp_get_next_count_tx(pdcp_entity, pdcp_header_len, current_sn);
encrypt_params.key_length = 16;
if (rb_id < DTCH) {
/* SRBs */
u8 *mac_i;
LOG_D(PDCP, "[OSA][RB %d] %s Applying control-plane security\n",
rb_id, (pdcp_entity->is_ue != 0) ? "UE -> eNB" : "eNB -> UE");
encrypt_params.message = pdcp_pdu_buffer;
encrypt_params.blength = (pdcp_header_len + sdu_buffer_size) << 3;
encrypt_params.key = pdcp_entity->kRRCint;
mac_i = &pdcp_pdu_buffer[pdcp_header_len + sdu_buffer_size];
/* Both header and data parts are integrity protected for
* control-plane PDUs */
stream_compute_integrity(pdcp_entity->integrityProtAlgorithm, &encrypt_params,
mac_i);
encrypt_params.key = pdcp_entity->kRRCenc;
} else {
LOG_D(PDCP, "[OSA][RB %d] %s Applying user-plane security\n",
rb_id, (pdcp_entity->is_ue != 0) ? "UE -> eNB" : "eNB -> UE");
encrypt_params.key = pdcp_entity->kUPenc;
}
encrypt_params.message = &pdcp_pdu_buffer[pdcp_header_len];
encrypt_params.blength = sdu_buffer_size << 3;
buffer_encrypted = &pdcp_pdu_buffer[pdcp_header_len];
/* Apply ciphering if any requested */
stream_encrypt(pdcp_entity->cipheringAlgorithm, &encrypt_params,
&buffer_encrypted);
return 0;
}
int pdcp_validate_security(pdcp_t *pdcp_entity, rb_id_t rb_id,
u8 pdcp_header_len, u16 current_sn, u8 *pdcp_pdu_buffer,
u16 sdu_buffer_size)
{
u8 *buffer_decrypted = NULL;
stream_cipher_t decrypt_params;
DevAssert(pdcp_entity != NULL);
DevAssert(pdcp_pdu_buffer != NULL);
DevCheck(rb_id < NB_RB_MAX && rb_id >= 0, rb_id, NB_RB_MAX, 0);
buffer_decrypted = (u8*)&pdcp_pdu_buffer[pdcp_header_len];
decrypt_params.direction = (pdcp_entity->is_ue == 1) ? SECU_DIRECTION_DOWNLINK : SECU_DIRECTION_UPLINK ;
decrypt_params.bearer = rb_id;
decrypt_params.count = pdcp_get_next_count_rx(pdcp_entity, pdcp_header_len, current_sn);
decrypt_params.message = &pdcp_pdu_buffer[pdcp_header_len];
decrypt_params.blength = (sdu_buffer_size - pdcp_header_len) << 3;
decrypt_params.key_length = 16;
if (rb_id < DTCH) {
LOG_D(PDCP, "[OSA][RB %d] %s Validating control-plane security\n",
rb_id, (pdcp_entity->is_ue != 0) ? "eNB -> UE" : "UE -> eNB");
decrypt_params.key = pdcp_entity->kRRCenc;
} else {
LOG_D(PDCP, "[OSA][RB %d] %s Validating user-plane security\n",
rb_id, (pdcp_entity->is_ue != 0) ? "eNB -> UE" : "UE -> eNB");
decrypt_params.key = pdcp_entity->kUPenc;
}
/* Uncipher the block */
stream_decrypt(pdcp_entity->cipheringAlgorithm, &decrypt_params, &buffer_decrypted);
if (rb_id < DTCH) {
/* Now check the integrity of the complete PDU */
decrypt_params.message = pdcp_pdu_buffer;
decrypt_params.blength = sdu_buffer_size << 3;
decrypt_params.key = pdcp_entity->kRRCint;
if (stream_check_integrity(pdcp_entity->integrityProtAlgorithm,
&decrypt_params, &pdcp_pdu_buffer[sdu_buffer_size]) != 0) {
LOG_E(PDCP, "[OSA] failed to validate MAC-I of incoming PDU\n");
return -1;
}
}
return 0;
}
#endif /* ENABLE_SECURITY */
......@@ -36,12 +36,22 @@
# @ingroup _mac
*/
#ifndef USER_MODE
#ifdef USER_MODE
# include <inttypes.h>
#else
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
# ifndef PRIu64
# if __WORDSIZE == 64
# define PRIu64 "lu"
# else
# define PRIu64 "llu"
# endif
# endif
#endif
#include "LAYER2/RLC/rlc.h"
#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/extern.h"
......@@ -114,7 +124,10 @@ int dump_eNB_l2_stats(char *buffer, int length){
eNB_mac_inst[eNB_id].eNB_UE_stats[UE_id].ncce_used_retx
);
len += sprintf(&buffer[len],"[MAC] DLSCH bitrate (TTI %d, avg %d), Transmitted bytes (TTI %d, total %d), Total Transmitted PDU %d, Overhead (TTI %d, total %d, avg %d)",
len += sprintf(&buffer[len],
"[MAC] DLSCH bitrate (TTI %d, avg %d), Transmitted bytes "
"(TTI %d, total %"PRIu64"), Total Transmitted PDU %d, Overhead "
"(TTI %"PRIu64", total %"PRIu64", avg %"PRIu64,
eNB_mac_inst[eNB_id].eNB_UE_stats[UE_id].dlsch_bitrate,
eNB_mac_inst[eNB_id].eNB_UE_stats[UE_id].total_dlsch_bitrate,
eNB_mac_inst[eNB_id].eNB_UE_stats[UE_id].TBS,
......
......@@ -772,7 +772,7 @@ uint8_t do_SIB23(uint8_t Mod_id,
*(*sib3)->intraFreqCellReselectionInfo.s_IntraSearch = 31;
(*sib3)->intraFreqCellReselectionInfo.allowedMeasBandwidth=CALLOC(1,sizeof(*(*sib3)->intraFreqCellReselectionInfo.allowedMeasBandwidth));
(*sib3)->intraFreqCellReselectionInfo.allowedMeasBandwidth=AllowedMeasBandwidth_mbw6;
*(*sib3)->intraFreqCellReselectionInfo.allowedMeasBandwidth = AllowedMeasBandwidth_mbw6;
(*sib3)->intraFreqCellReselectionInfo.presenceAntennaPort1 = 0;
(*sib3)->intraFreqCellReselectionInfo.neighCellConfig.buf = CALLOC(8,1);
......@@ -1299,25 +1299,28 @@ uint8_t do_RRCConnectionSetup(uint8_t *buffer,
return((enc_rval.encoded+7)/8);
}
uint8_t do_SecurityModeCommand(uint8_t Mod_id,
uint8_t *buffer,
uint8_t UE_id,
uint8_t Transaction_id) {
uint8_t *buffer,
uint8_t UE_id,
uint8_t Transaction_id,
uint8_t cipheringAlgorithm,
uint8_t integrityProtAlgorithm) {
DL_DCCH_Message_t dl_dcch_msg;
asn_enc_rval_t enc_rval;
memset(&dl_dcch_msg,0,sizeof(DL_DCCH_Message_t));
dl_dcch_msg.message.present = DL_DCCH_MessageType_PR_c1;
dl_dcch_msg.message.choice.c1.present = DL_DCCH_MessageType__c1_PR_securityModeCommand;
dl_dcch_msg.message.choice.c1.choice.securityModeCommand.rrc_TransactionIdentifier = Transaction_id;
dl_dcch_msg.message.choice.c1.choice.securityModeCommand.criticalExtensions.present = SecurityModeCommand__criticalExtensions_PR_c1;
dl_dcch_msg.message.choice.c1.choice.securityModeCommand.criticalExtensions.choice.c1.present = SecurityModeCommand__criticalExtensions__c1_PR_securityModeCommand_r8;
// the two following information could be based on the mod_id
dl_dcch_msg.message.choice.c1.choice.securityModeCommand.criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm=SecurityAlgorithmConfig__cipheringAlgorithm_spare1;
dl_dcch_msg.message.choice.c1.choice.securityModeCommand.criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm=SecurityAlgorithmConfig__integrityProtAlgorithm_spare1;
dl_dcch_msg.message.present = DL_DCCH_MessageType_PR_c1;
dl_dcch_msg.message.choice.c1.present = DL_DCCH_MessageType__c1_PR_securityModeCommand;
dl_dcch_msg.message.choice.c1.choice.securityModeCommand.rrc_TransactionIdentifier = Transaction_id;
dl_dcch_msg.message.choice.c1.choice.securityModeCommand.criticalExtensions.present = SecurityModeCommand__criticalExtensions_PR_c1;
dl_dcch_msg.message.choice.c1.choice.securityModeCommand.criticalExtensions.choice.c1.present = SecurityModeCommand__criticalExtensions__c1_PR_securityModeCommand_r8;
// the two following information could be based on the mod_id
dl_dcch_msg.message.choice.c1.choice.securityModeCommand.criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm
= (e_SecurityAlgorithmConfig__cipheringAlgorithm)cipheringAlgorithm;
dl_dcch_msg.message.choice.c1.choice.securityModeCommand.criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm
= (e_SecurityAlgorithmConfig__integrityProtAlgorithm)integrityProtAlgorithm;
#ifdef XER_PRINT
xer_fprint(stdout, &asn_DEF_DL_DCCH_Message, (void*)&dl_dcch_msg);
......@@ -1680,7 +1683,7 @@ uint8_t do_MeasurementReport(uint8_t *buffer,int measid,int phy_id,int rsrp_s,in
100);
#ifdef USER_MODE
printf("Measurement Report Encoded %d bits (%d bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
printf("Measurement Report Encoded %zu bits (%zu bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
#endif
return((enc_rval.encoded+7)/8);
......
......@@ -141,6 +141,8 @@ uint8_t do_UECapabilityEnquiry(uint8_t Mod_id,
uint8_t Transaction_id);
uint8_t do_SecurityModeCommand(uint8_t Mod_id,
uint8_t *buffer,
uint8_t UE_id,
uint8_t Transaction_id);
uint8_t *buffer,
uint8_t UE_id,
uint8_t Transaction_id,
uint8_t cipheringAlgorithm,
uint8_t integrityProtAlgorithm);
......@@ -240,6 +240,15 @@ typedef struct{
SRB_INFO Srb0;
SRB_INFO_TABLE_ENTRY Srb1[NUMBER_OF_UE_MAX+1];
SRB_INFO_TABLE_ENTRY Srb2[NUMBER_OF_UE_MAX+1];
#if defined(ENABLE_SECURITY)
/* KeNB as derived from KASME received from EPC */
uint8_t kenb[NUMBER_OF_UE_MAX][32];
#endif
/* Used integrity/ciphering algorithms */
e_SecurityAlgorithmConfig__cipheringAlgorithm ciphering_algorithm[NUMBER_OF_UE_MAX];
e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm[NUMBER_OF_UE_MAX];
} eNB_RRC_INST;
#define MAX_UE_CAPABILITY_SIZE 255
......@@ -300,6 +309,15 @@ typedef struct{
struct SPS_Config *sps_Config[NB_CNX_UE];
MAC_MainConfig_t *mac_MainConfig[NB_CNX_UE];
MeasGapConfig_t *measGapConfig[NB_CNX_UE];
#if defined(ENABLE_SECURITY)
/* KeNB as computed from parameters within USIM card */
uint8_t kenb[32];
#endif
/* Used integrity/ciphering algorithms */
e_SecurityAlgorithmConfig__cipheringAlgorithm ciphering_algorithm;
e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm;
}UE_RRC_INST;
//main.c
......
......@@ -68,6 +68,11 @@
#include "RRC/NAS/nas_config.h"
#include "RRC/NAS/rb_config.h"
#endif
#if defined(ENABLE_SECURITY)
# include "UTIL/OSA/osa_defs.h"
#endif
#ifdef PHY_EMUL
extern EMULATION_VARS *Emul_vars;
#endif
......@@ -110,9 +115,29 @@ void init_MCCH_UE(u8 Mod_id, u8 eNB_index) {
UE_rrc_inst[Mod_id].MCCH_MESSAGE[eNB_index] = (u8 *)malloc16(32);
UE_rrc_inst[Mod_id].mcch_message[eNB_index] = (MBSFNAreaConfiguration_r9_t *)malloc16(sizeof(MBSFNAreaConfiguration_r9_t));
UE_rrc_inst[Mod_id].Info[eNB_index].MCCH_MESSAGEStatus = 0;
}
}
#endif
static
void openair_rrc_lite_ue_init_security(u8 Mod_id)
{
#if defined(ENABLE_SECURITY)
uint8_t *kRRCenc;
uint8_t *kRRCint;
char ascii_buffer[65];
uint8_t i;
memset(UE_rrc_inst[Mod_id].kenb, Mod_id, 32);
for (i = 0; i < 32; i++) {
sprintf(&ascii_buffer[2 * i], "%02X", UE_rrc_inst[Mod_id].kenb[i]);
}
LOG_T(RRC, "[OSA][UE %02d] kenb = %s\n",
Mod_id, ascii_buffer);
#endif
}
/*------------------------------------------------------------------------------*/
char openair_rrc_lite_ue_init(u8 Mod_id, unsigned char eNB_index){
......@@ -130,6 +155,15 @@ char openair_rrc_lite_ue_init(u8 Mod_id, unsigned char eNB_index){
UE_rrc_inst[Mod_id].Srb1[eNB_index].Active=0;
UE_rrc_inst[Mod_id].Srb2[eNB_index].Active=0;
UE_rrc_inst[Mod_id].ciphering_algorithm = SecurityAlgorithmConfig__cipheringAlgorithm_eea0;
#ifdef Rel10
UE_rrc_inst[Mod_id].integrity_algorithm = SecurityAlgorithmConfig__integrityProtAlgorithm_eia0_v920;
#else
UE_rrc_inst[Mod_id].integrity_algorithm = SecurityAlgorithmConfig__integrityProtAlgorithm_reserved;
#endif
openair_rrc_lite_ue_init_security(Mod_id);
init_SI_UE(Mod_id,eNB_index);
LOG_D(RRC,"[UE %d] INIT: phy_sync_2_ch_ind\n", Mod_id);
......@@ -652,12 +686,26 @@ void rrc_ue_process_radioResourceConfigDedicated(u8 Mod_id,u32 frame, u8 eNB_ind
// Establish SRBs if present
// loop through SRBToAddModList
if (radioResourceConfigDedicated->srb_ToAddModList) {
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
#if defined(ENABLE_SECURITY)
derive_key_rrc_enc(UE_rrc_inst[Mod_id].ciphering_algorithm,
UE_rrc_inst[Mod_id].kenb, &kRRCenc);
derive_key_rrc_int(UE_rrc_inst[Mod_id].integrity_algorithm,
UE_rrc_inst[Mod_id].kenb, &kRRCint);
#endif
// Refresh SRBs
rrc_pdcp_config_asn1_req(NB_eNB_INST+Mod_id,frame,0,eNB_index,
radioResourceConfigDedicated->srb_ToAddModList,
(DRB_ToAddModList_t*)NULL,
(DRB_ToReleaseList_t*)NULL
radioResourceConfigDedicated->srb_ToAddModList,
(DRB_ToAddModList_t*)NULL,
(DRB_ToReleaseList_t*)NULL,
UE_rrc_inst[Mod_id].ciphering_algorithm |
(UE_rrc_inst[Mod_id].integrity_algorithm << 4),
kRRCenc,
kRRCint,
NULL
#ifdef Rel10
,(MBMS_SessionInfoList_r9_t *)NULL
#endif
......@@ -790,12 +838,23 @@ void rrc_ue_process_radioResourceConfigDedicated(u8 Mod_id,u32 frame, u8 eNB_ind
// Establish DRBs if present
if (radioResourceConfigDedicated->drb_ToAddModList) {
uint8_t *kUPenc;
#if defined(ENABLE_SECURITY)
derive_key_up_enc(UE_rrc_inst[Mod_id].integrity_algorithm,
UE_rrc_inst[Mod_id].kenb, &kUPenc);
#endif
// Refresh DRBs
rrc_pdcp_config_asn1_req(NB_eNB_INST+Mod_id,frame,0,eNB_index,
(SRB_ToAddModList_t*)NULL,
radioResourceConfigDedicated->drb_ToAddModList,
(DRB_ToReleaseList_t*)NULL
(SRB_ToAddModList_t*)NULL,
radioResourceConfigDedicated->drb_ToAddModList,
(DRB_ToReleaseList_t*)NULL,
UE_rrc_inst[Mod_id].ciphering_algorithm |
(UE_rrc_inst[Mod_id].integrity_algorithm << 4),
NULL,
NULL,
kUPenc
#ifdef Rel10
,(MBMS_SessionInfoList_r9_t *)NULL
#endif
......@@ -907,7 +966,11 @@ void rrc_ue_process_securityModeCommand(uint8_t Mod_id,uint32_t frame,SecurityMo
break;
}
LOG_D(RRC,"[UE %d] security mode is %x \n",Mod_id, securityMode);
/* Store the parameters received */
UE_rrc_inst[Mod_id].ciphering_algorithm = securityModeCommand->criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm;
UE_rrc_inst[Mod_id].integrity_algorithm = securityModeCommand->criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm;
memset((void *)&ul_dcch_msg,0,sizeof(UL_DCCH_Message_t));
//memset((void *)&SecurityModeCommand,0,sizeof(SecurityModeCommand_t));
......@@ -1035,8 +1098,7 @@ void rrc_ue_process_rrcConnectionReconfiguration(u8 Mod_id, u32 frame,
if (rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated) {
LOG_I(RRC,"Radio Resource Configuration is present\n");
rrc_ue_process_radioResourceConfigDedicated(Mod_id,frame,eNB_index,
rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated);
rrcConnectionReconfiguration->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r8.radioResourceConfigDedicated);
}
} // c1 present
} // critical extensions present
......@@ -1219,6 +1281,7 @@ int decode_BCCH_DLSCH_Message(u8 Mod_id,u32 frame,u8 eNB_index,u8 *Sdu,u8 Sdu_le
}
break;
case BCCH_DL_SCH_MessageType__c1_PR_NOTHING:
default:
break;
}
}
......@@ -1227,6 +1290,8 @@ int decode_BCCH_DLSCH_Message(u8 Mod_id,u32 frame,u8 eNB_index,u8 *Sdu,u8 Sdu_le
(UE_rrc_inst[Mod_id].Info[eNB_index].SIStatus == 1) && (frame >= Mod_id * 20 + 10))
SEQUENCE_free(&asn_DEF_BCCH_DL_SCH_Message, (void*)bcch_message, 0);*/
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT);
return 0;
}
......@@ -1385,10 +1450,10 @@ void dump_sib2(SystemInformationBlockType2_t *sib2) {
LOG_D(RRC,"ue_TimersAndConstants.n311 : %ld\n", sib2->ue_TimersAndConstants.n311);
LOG_D(RRC,"freqInfo.additionalSpectrumEmission : %ld\n",sib2->freqInfo.additionalSpectrumEmission);
LOG_D(RRC,"freqInfo.ul_CarrierFreq : %d\n",(int)sib2->freqInfo.ul_CarrierFreq);
LOG_D(RRC,"freqInfo.ul_Bandwidth : %d\n",(int)sib2->freqInfo.ul_Bandwidth);
LOG_D(RRC,"mbsfn_SubframeConfigList : %d\n",(int)sib2->mbsfn_SubframeConfigList);
LOG_D(RRC,"timeAlignmentTimerCommon : %ld\n",sib2->timeAlignmentTimerCommon);
LOG_D(RRC,"freqInfo.ul_CarrierFreq : %ld\n", sib2->freqInfo.ul_CarrierFreq);
LOG_D(RRC,"freqInfo.ul_Bandwidth : %ld\n", sib2->freqInfo.ul_Bandwidth);
LOG_D(RRC,"mbsfn_SubframeConfigList : %ld\n", sib2->mbsfn_SubframeConfigList);
LOG_D(RRC,"timeAlignmentTimerCommon : %ld\n", sib2->timeAlignmentTimerCommon);
......
......@@ -64,6 +64,10 @@
#include "OCG_extern.h"
#endif
#if defined(ENABLE_SECURITY)
# include "UTIL/OSA/osa_defs.h"
#endif
#if defined(ENABLE_USE_MME)
#include "../../S1AP/s1ap_eNB.h"
#endif
......@@ -412,6 +416,23 @@ init_MBMS (u8 Mod_id, u32 frame)
#endif
static
void rrc_lite_eNB_init_security(u8 Mod_id, u8 UE_index)
{
#if defined(ENABLE_SECURITY)
char ascii_buffer[65];
uint8_t i;
memset(eNB_rrc_inst[Mod_id].kenb[UE_index], UE_index, 32);
for (i = 0; i < 32; i++) {
sprintf(&ascii_buffer[2 * i], "%02X", eNB_rrc_inst[Mod_id].kenb[UE_index][i]);
}
LOG_T(RRC, "[OSA][MOD %02d][UE %02d] kenb = %s\n", Mod_id, UE_index, ascii_buffer);
#endif
}
/*------------------------------------------------------------------------------*/
char
openair_rrc_lite_eNB_init (u8 Mod_id)
......@@ -426,6 +447,13 @@ openair_rrc_lite_eNB_init (u8 Mod_id)
for (j = 0; j < NUMBER_OF_UE_MAX; j++)
eNB_rrc_inst[Mod_id].Info.Status[j] = RRC_IDLE; //CH_READY;
/* Init security parameters */
for (j = 0; j < NUMBER_OF_UE_MAX; j++) {
eNB_rrc_inst[Mod_id].ciphering_algorithm[j] = SecurityAlgorithmConfig__cipheringAlgorithm_eea2;
eNB_rrc_inst[Mod_id].integrity_algorithm[j] = SecurityAlgorithmConfig__integrityProtAlgorithm_eia2;
rrc_lite_eNB_init_security(Mod_id, j);
}
#if defined(ENABLE_USE_MME)
/* Connect eNB to MME */
if (oai_emulation.info.mme_enabled > 0)
......@@ -931,7 +959,11 @@ rrc_eNB_decode_ccch (u8 Mod_id, u32 frame, SRB_INFO * Srb_info)
eNB_rrc_inst[Mod_id].
SRB_configList[UE_index],
(DRB_ToAddModList_t *) NULL,
(DRB_ToReleaseList_t *) NULL
(DRB_ToReleaseList_t *) NULL,
0xff,
NULL,
NULL,
NULL
#ifdef Rel10
, (PMCH_InfoList_r9_t *) NULL
#endif
......@@ -1017,7 +1049,9 @@ rrc_eNB_generate_SecurityModeCommand (u8 Mod_id, u32 frame, u16 UE_index)
uint8_t buffer[100];
uint8_t size;
size = do_SecurityModeCommand (Mod_id, buffer, UE_index, 0);
size = do_SecurityModeCommand (Mod_id, buffer, UE_index, 0,
eNB_rrc_inst[Mod_id].ciphering_algorithm[UE_index],
eNB_rrc_inst[Mod_id].integrity_algorithm[UE_index]);
LOG_I (RRC,
"[eNB %d] Frame %d, Logical Channel DL-DCCH, Generate SecurityModeCommand (bytes %d, UE id %d)\n",
......@@ -1611,15 +1645,38 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete (u8 Mod_id, u32 frame,
int oip_ifup = 0;
int dest_ip_offset = 0;
#endif
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t *kUPenc = NULL;
DRB_ToAddModList_t *DRB_configList =
eNB_rrc_inst[Mod_id].DRB_configList[UE_index];
SRB_ToAddModList_t *SRB_configList =
eNB_rrc_inst[Mod_id].SRB_configList[UE_index];
#if defined(ENABLE_SECURITY)
/* Derive the keys from kenb */
if (DRB_configList != NULL) {
derive_key_up_enc(eNB_rrc_inst[Mod_id].ciphering_algorithm[UE_index],
eNB_rrc_inst[Mod_id].kenb[UE_index], &kUPenc);
}
derive_key_rrc_enc(eNB_rrc_inst[Mod_id].ciphering_algorithm[UE_index],
eNB_rrc_inst[Mod_id].kenb[UE_index], &kRRCenc);
derive_key_rrc_int(eNB_rrc_inst[Mod_id].integrity_algorithm[UE_index],
eNB_rrc_inst[Mod_id].kenb[UE_index], &kRRCint);
#endif
// Refresh SRBs/DRBs
rrc_pdcp_config_asn1_req (Mod_id, frame, 1, UE_index,
SRB_configList,
DRB_configList, (DRB_ToReleaseList_t *) NULL
DRB_configList, (DRB_ToReleaseList_t *) NULL,
eNB_rrc_inst[Mod_id].ciphering_algorithm[UE_index] |
(eNB_rrc_inst[Mod_id].integrity_algorithm[UE_index] << 4),
kRRCenc,
kRRCint,
kUPenc
#ifdef Rel10
, (PMCH_InfoList_r9_t *) NULL
#endif
......
......@@ -281,6 +281,14 @@ int logInit (void) {
g_log->log_component[HW].filelog = 0;
g_log->log_component[HW].filelog_name = "";
g_log->log_component[OSA].name = "OSA";
g_log->log_component[OSA].level = LOG_EMERG;
g_log->log_component[OSA].flag = LOG_MED;
g_log->log_component[OSA].interval = 1;
g_log->log_component[OSA].fd = 0;
g_log->log_component[OSA].filelog = 0;
g_log->log_component[OSA].filelog_name = "";
g_log->level2string[LOG_EMERG] = "G"; //EMERG
g_log->level2string[LOG_ALERT] = "A"; // ALERT
g_log->level2string[LOG_CRIT] = "C"; // CRITIC
......
......@@ -231,7 +231,34 @@ extern "C" {
//static char *log_level_highlight_end[] = {LOG_RESET, LOG_RESET, LOG_RESET, LOG_RESET, LOG_RESET, "", "", "", LOG_RESET}; /*!< \brief Optional end-format strings for highlighting */
typedef enum {MIN_LOG_COMPONENTS=0, PHY, MAC, EMU, OCG, OMG,OPT,OTG,OTG_LATENCY,OTG_LATENCY_BG, OTG_GP, OTG_GP_BG,OTG_JITTER, RLC, PDCP, RRC, PERF,OIP, CLI, MSC, OCM, S1AP, SCTP, HW, MAX_LOG_COMPONENTS} comp_name_t;
typedef enum {
MIN_LOG_COMPONENTS = 0,
PHY,
MAC,
EMU,
OCG,
OMG,
OPT,
OTG,
OTG_LATENCY,
OTG_LATENCY_BG,
OTG_GP,
OTG_GP_BG,
OTG_JITTER,
RLC,
PDCP,
RRC,
PERF,
OIP,
CLI,
MSC,
OCM,
S1AP,
SCTP,
HW,
OSA,
MAX_LOG_COMPONENTS
} comp_name_t;
//#define msg printf
......
......@@ -12,6 +12,7 @@ CLI_DIR=$(OPENAIR2_TOP)/UTIL/CLI
OMV_DIR=$(OPENAIR2_TOP)/UTIL/OMV
SCTP_DIR=$(OPENAIR2_TOP)/UTIL/SCTP
LFDS_DIR=$(OPENAIR2_TOP)/UTIL/LFDS/liblfds6.1.1/liblfds611
OSA_DIR=$(OPENAIR2_TOP)/UTIL/OSA
LIST_OBJ = $(LIST_DIR)/list.o
......@@ -34,6 +35,12 @@ OCG_OBJS += $(OCG_DIR)/OCG_parse_filename.o
OCG_OBJS += $(OCG_DIR)/OCG_parse_XML.o
OCG_OBJS += $(OCG_DIR)/OCG_save_XML.o
ifdef SECU
OSA_OBJS = $(OSA_DIR)/osa_key_deriver.o
OSA_OBJS += $(OSA_DIR)/osa_stream_eia.o
OSA_OBJS += $(OSA_DIR)/osa_stream_eea.o
endif
OPT_OBJS = $(OPT_DIR)/probe.o
OMG_OBJS = $(OMG_DIR)/omg.o
......@@ -69,6 +76,22 @@ SCTP_OBJS = $(SCTP_DIR)/sctp_primitives_client.o
else
SCTP_OBJS =
endif
UTIL_OBJ = $(FIFO_OBJ) $(LIST_OBJ) $(TIMER_OBJ) $(MEM_OBJ) $(LOG_OBJS) $(OCG_OBJS) $(MATH_OBJS) $(OTG_OBJS) $(CLI_OBJ) $(OMG_OBJS) $(OPT_OBJS) $(SCTP_OBJS)
UTIL_OBJ = $(OSA_OBJS) $(FIFO_OBJ) $(LIST_OBJ) $(TIMER_OBJ) $(MEM_OBJ) $(LOG_OBJS) $(OCG_OBJS) $(MATH_OBJS) $(OTG_OBJS) $(CLI_OBJ) $(OMG_OBJS) $(OPT_OBJS) $(SCTP_OBJS)
UTIL_incl = -I$(LFDS_DIR)/inc -I$(MEM_DIR) -I$(LIST_DIR) -I$(FIFO_DIR) -I$(OCG_DIR) -I$(LOG_DIR) -I$(MATH_DIR) -I$(TIMER_DIR) -I$(OMG_DIR) -I$(OTG_DIR) -I$(CLI_DIR) -I$(OPT_DIR) -I$(OMV_DIR) -I$(SCTP_DIR)
UTIL_incl = \
-I$(OPENAIR2_TOP)/UTIL \
-I$(OSA_DIR) \
-I$(LFDS_DIR)/inc \
-I$(MEM_DIR) \
-I$(LIST_DIR) \
-I$(FIFO_DIR) \
-I$(OCG_DIR) \
-I$(LOG_DIR) \
-I$(MATH_DIR) \
-I$(TIMER_DIR) \
-I$(OMG_DIR) \
-I$(OTG_DIR) \
-I$(CLI_DIR) \
-I$(OPT_DIR) \
-I$(OMV_DIR) \
-I$(SCTP_DIR)
OAISIM Security Algorithms v0.1
Dependencies:
- nettle >= 2.5
- openssl >= 1.0.1
Compilation:
When compiling oaisim, add SECU=1 to enable security features. The makefile will
check for required dependencies and disable this feature if not all dependencies
are met.
OSA is based on 3GPP TS 33.401.
Note that only EEA2 and EIA2 algorithms are supported, SNOW-3G is not implemented.
Currently the kenb used to derive kRRCint, kRRCenc and kUPenc is composed of the
UE_id. In the future this parameter can be either obtained by deriving KASME received
from core epc (in the S1AP initial context setup request)
or configurable via command line or XML file.
/*******************************************************************************
Eurecom OpenAirInterface
Copyright(c) 1999 - 2013 Eurecom
This program is free software; you can redistribute it and/or modify it
under the terms and conditions of the GNU General Public License,
version 2, as published by the Free Software Foundation.
This program is distributed in the hope it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
The full GNU General Public License is included in this distribution in
the file called "COPYING".
Contact Information
Openair Admin: openair_admin@eurecom.fr
Openair Tech : openair_tech@eurecom.fr
Forums : http://forums.eurecom.fr/openairinterface
Address : EURECOM, Campus SophiaTech, 450 Route des Chappes
06410 Biot FRANCE
*******************************************************************************/
/*!
* \file secu_defs.h
* \brief Openair security algorithms functions implementing 3GPP TS 33.401
* \note HMAC computations are done by nettle/openssl library
* \author Sebastien ROUX
* \date 2013
* \version 0.1
* @ingroup security
*/
#ifndef SECU_DEFS_H_
#define SECU_DEFS_H_
#define EIA0_ALG_ID 0x00
#define EIA1_128_ALG_ID 0x01
#define EIA2_128_ALG_ID 0x02
#define EEA0_ALG_ID EIA0_ALG_ID
#define EEA1_128_ALG_ID EIA1_128_ALG_ID
#define EEA2_128_ALG_ID EIA2_128_ALG_ID
#define SECU_DIRECTION_UPLINK 0
#define SECU_DIRECTION_DOWNLINK 1
typedef enum {
NAS_ENC_ALG = 0x01,
NAS_INT_ALG = 0x02,
RRC_ENC_ALG = 0x03,
RRC_INT_ALG = 0x04,
UP_ENC_ALG = 0x05
} algorithm_type_dist_t;
int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keNB);
int derive_key(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
const uint8_t key[32], uint8_t **out);
#define derive_key_nas_enc(aLGiD, kEY, kNAS) \
derive_key(NAS_ENC_ALG, aLGiD, kEY, kNAS)
#define derive_key_nas_int(aLGiD, kEY, kNAS) \
derive_key(NAS_INT_ALG, aLGiD, kEY, kNAS)
#define derive_key_rrc_enc(aLGiD, kEY, kNAS) \
derive_key(RRC_ENC_ALG, aLGiD, kEY, kNAS)
#define derive_key_rrc_int(aLGiD, kEY, kNAS) \
derive_key(RRC_INT_ALG, aLGiD, kEY, kNAS)
#define derive_key_up_enc(aLGiD, kEY, kNAS) \
derive_key(UP_ENC_ALG, aLGiD, kEY, kNAS)
#define derive_key_up_int(aLGiD, kEY, kNAS) \
derive_key(UP_INT_ALG, aLGiD, kEY, kNAS)
typedef struct {
uint8_t *key;
uint32_t key_length;
uint32_t count;
uint8_t bearer;
uint8_t direction;
uint8_t *message;
/* length in bits */
uint32_t blength;
} stream_cipher_t;
/*!
* @brief Encrypt/Decrypt a block of data based on the provided algorithm
* @param[in] algorithm Algorithm used to encrypt the data
* Possible values are:
* - EIA0_ALG_ID for NULL encryption
* - EIA1_128_ALG_ID for SNOW-3G encryption (not avalaible right now)
* - EIA2_128_ALG_ID for 128 bits AES LTE encryption
* @param[in] stream_cipher All parameters used to compute the encrypted block of data
* @param[out] out The encrypted block of data dynamically allocated
* @return 0 if everything OK, -1 if something failed
*/
int stream_encrypt(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t **out);
#define stream_decrypt stream_encrypt
int stream_compute_integrity(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t out[4]);
/*!
* @brief Decrypt a block of data based on the provided algorithm
* @param[in] algorithm Algorithm used to encrypt the data
* Possible values are:
* - EIA0_ALG_ID for NULL encryption
* - EIA1_128_ALG_ID for SNOW-3G encryption (not avalaible right now)
* - EIA2_128_ALG_ID for 128 bits AES LTE encryption
* @param[in] stream_cipher All parameters used to compute the decrypted block of data
* @param[out] out The decrypted block of data dynamically allocated
* @return 0 if everything OK, -1 if something failed
*/
int stream_decrypt(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t **out);
int stream_check_integrity(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t *expected);
#undef SECU_DEBUG
#endif /* SECU_DEFS_H_ */
#ifndef OSA_INTERNAL_H_
#define OSA_INTERNAL_H_
#define FC_KENB (0x11)
#define FC_NH (0x12)
#define FC_KENB_STAR (0x13)
/* 33401 #A.7 Algorithm for key derivation function.
* This FC should be used for:
* - NAS Encryption algorithm
* - NAS Integrity algorithm
* - RRC Encryption algorithm
* - RRC Integrity algorithm
* - User Plane Encryption algorithm
*/
#define FC_ALG_KEY_DER (0x15)
#define FC_KASME_TO_CK (0x16)
#ifndef hton_int32
# define hton_int32(x) \
(((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) | \
((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24))
#endif
#define SECU_DEBUG
#endif /* OSA_INTERNAL_H_ */
#include <stdint.h>
#include <nettle/hmac.h>
#include "osa_defs.h"
#include "osa_internal.h"
#include "UTIL/LOG/log.h"
static inline
void kdf(const uint8_t *s, const uint32_t s_length, const uint8_t *key,
const uint32_t key_length, uint8_t **out, uint32_t out_length)
{
struct hmac_sha256_ctx ctx;
uint8_t *buffer;
buffer = malloc(sizeof(uint8_t) * out_length);
hmac_sha256_set_key(&ctx, key_length, key);
hmac_sha256_update(&ctx, s_length, s);
hmac_sha256_digest(&ctx, out_length, buffer);
*out = buffer;
}
/*!
* @brief Derive the keys from kasme and perform truncate on the generated key to
* reduce his size to 128 bits. Definition of the derivation function can
* be found in 3GPP TS.33401 #A.7
* @param[in] alg_type Algorithm distinguisher
* @param[in] alg_id Algorithm identifier.
* Possible values are:
* - 0 for EIA0 algorithm (Null Integrity Protection algorithm)
* - 1 for 128-EIA1 SNOW 3G
* - 2 for 128-EIA2 AES
* @param[in] key The top key used to derive other subkeys
* @param[out] out Pointer to reference where output of KDF will be stored.
* NOTE: knas is dynamically allocated by the KDF function
*/
int derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id,
const uint8_t key[32], uint8_t **out)
{
uint8_t string[7];
#if defined(SECU_DEBUG)
int i;
#endif
/* FC */
string[0] = FC_ALG_KEY_DER;
/* P0 = algorithm type distinguisher */
string[1] = (uint8_t)(alg_type & 0xFF);
/* L0 = length(P0) = 1 */
string[2] = 0x00;
string[3] = 0x01;
/* P1 */
string[4] = alg_id;
/* L1 = length(P1) = 1 */
string[5] = 0x00;
string[6] = 0x01;
#if defined(SECU_DEBUG)
{
int i;
char payload[6 * sizeof(string) + 1];
int index = 0;
for (i = 0; i < sizeof(string); i++)
index += sprintf(&payload[index], "0x%02x ", string[i]);
LOG_D(OSA, "Key deriver input string: %s\n", payload);
}
#endif
kdf(string, 7, key, 32, out, 32);
return 0;
}
int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keNB)
{
uint8_t string[7];
/* FC */
string[0] = FC_KENB;
/* P0 = Uplink NAS count */
string[1] = (nas_count & 0xff000000) >> 24;
string[2] = (nas_count & 0x00ff0000) >> 16;
string[3] = (nas_count & 0x0000ff00) >> 8;
string[4] = (nas_count & 0x000000ff);
/* Length of NAS count */
string[5] = 0x00;
string[6] = 0x04;
#if defined(SECU_DEBUG)
{
int i;
char payload[6 * sizeof(string) + 1];
int index = 0;
for (i = 0; i < sizeof(string); i++)
index += sprintf(&payload[index], "0x%02x ", string[i]);
LOG_D(OSA, "KeNB deriver input string: %s\n", payload);
}
#endif
kdf(string, 7, kasme, 32, keNB, 32);
return 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <nettle/nettle-meta.h>
#include <nettle/aes.h>
#include <nettle/ctr.h>
#include "UTIL/LOG/log.h"
#include "assertions.h"
#include "osa_defs.h"
#include "osa_internal.h"
int stream_encrypt_eea2(stream_cipher_t *stream_cipher, uint8_t **out)
{
uint8_t m[16];
uint32_t local_count;
void *ctx;
uint8_t *data = NULL;
uint32_t zero_bit = 0;
uint32_t byte_length;
DevAssert(stream_cipher != NULL);
DevAssert(out != NULL);
LOG_D(OSA, "Entering stream_encrypt_eea2, bits length %u, bearer %u, "
"count %u, direction %s\n", stream_cipher->blength,
stream_cipher->bearer, stream_cipher->count, stream_cipher->direction == SECU_DIRECTION_DOWNLINK ?
"Downlink" : "Uplink");
zero_bit = stream_cipher->blength & 0x7;
byte_length = stream_cipher->blength >> 3;
if (zero_bit > 0)
byte_length += 1;
ctx = malloc(nettle_aes128.context_size);
if (*out == NULL) {
/* User provided output buffer */
data = malloc(byte_length);
*out = data;
} else {
data = *out;
}
local_count = hton_int32(stream_cipher->count);
memset(m, 0, sizeof(m));
memcpy(&m[0], &local_count, 4);
m[4] = ((stream_cipher->bearer & 0x1F) << 3) |
((stream_cipher->direction & 0x01) << 2);
/* Other bits are 0 */
#if defined(SECU_DEBUG)
{
int i;
char payload[6 * byte_length + 1];
int index = 0;
for (i = 0; i < byte_length; i++)
index += sprintf(&payload[index], "0x%02x ", stream_cipher->message[i]);
LOG_D(OSA, "Original message: %s\n", payload);
}
#endif
nettle_aes128.set_encrypt_key(ctx, stream_cipher->key_length,
stream_cipher->key);
nettle_ctr_crypt(ctx, nettle_aes128.encrypt,
nettle_aes128.block_size, m,
byte_length, data, stream_cipher->message);
if (zero_bit > 0)
data[byte_length - 1] = data[byte_length - 1] & (uint8_t)(0xFF << (8 - zero_bit));
free(ctx);
#if defined(SECU_DEBUG)
{
int i;
char payload[6 * byte_length + 1];
int index = 0;
for (i = 0; i < byte_length; i++)
index += sprintf(&payload[index], "0x%02x ", data[i]);
LOG_D(OSA, "Encrypted message: %s\n", payload);
}
#endif
return 0;
}
int stream_encrypt(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t **out)
{
if (algorithm == EEA0_ALG_ID) {
// return stream_encrypt_eea0(stream_cipher, out);
} else if (algorithm == EEA1_128_ALG_ID) {
LOG_E(OSA, "SNOW-3G algorithms are currently not implemented\n");
return -1;
} else if (algorithm == EEA2_128_ALG_ID) {
return stream_encrypt_eea2(stream_cipher, out);
}
LOG_E(OSA, "Provided algorithm is currently not supported = %u\n", algorithm);
return -1;
}
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "assertions.h"
#include <openssl/aes.h>
#include <openssl/cmac.h>
#include <openssl/evp.h>
#include "UTIL/LOG/log.h"
#include "osa_defs.h"
#include "osa_internal.h"
/*!
* @brief Create integrity cmac t for a given message.
* @param[in] stream_cipher Structure containing various variables to setup encoding
* @param[out] out For EIA2 the output string is 32 bits long
*/
int stream_compute_integrity_eia2(stream_cipher_t *stream_cipher, uint8_t out[4])
{
uint8_t *m;
uint32_t local_count;
size_t size = 4;
uint8_t data[16];
CMAC_CTX *cmac_ctx;
uint32_t zero_bit = 0;
uint32_t m_length;
DevAssert(stream_cipher != NULL);
DevAssert(stream_cipher->key != NULL);
memset(data, 0, 16);
zero_bit = stream_cipher->blength & 0x7;
m_length = stream_cipher->blength >> 3;
if (zero_bit > 0)
m_length += 1;
local_count = hton_int32(stream_cipher->count);
m = calloc(m_length + 8, sizeof(uint8_t));
memcpy(&m[0], &local_count, 4);
m[4] = ((stream_cipher->bearer & 0x1F) << 3) | ((stream_cipher->direction & 0x01) << 2);
memcpy(&m[8], stream_cipher->message, m_length);
#if defined(SECU_DEBUG)
{
int i;
char payload[6 * sizeof(m) + 1];
int index = 0;
LOG_T(OSA, "Blength: %u, Zero bits: %u\n",
stream_cipher->blength, zero_bit);
for (i = 0; i < sizeof(m); i++)
index += sprintf(&payload[index], "0x%02x ", m[i]);
LOG_T(OSA, "Payload: %s\n", payload);
}
#endif
cmac_ctx = CMAC_CTX_new();
CMAC_Init(cmac_ctx, stream_cipher->key, stream_cipher->key_length, EVP_aes_128_cbc(), NULL);
CMAC_Update(cmac_ctx, m, m_length + 8);
CMAC_Final(cmac_ctx, data, &size);
CMAC_CTX_free(cmac_ctx);
memcpy(out, data, 4);
free(m);
return 0;
}
int stream_compute_integrity(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t out[4])
{
if (algorithm == EIA0_ALG_ID) {
// return stream_encrypt_eea0(stream_cipher, out);
} else if (algorithm == EIA1_128_ALG_ID) {
LOG_E(OSA, "SNOW-3G algorithms are currently not implemented\n");
return -1;
} else if (algorithm == EIA2_128_ALG_ID) {
return stream_compute_integrity_eia2(stream_cipher, out);
}
LOG_E(OSA, "Provided algorithm is currently not supported = %u\n", algorithm);
return -1;
}
int stream_check_integrity(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t *expected)
{
uint8_t result[4];
if (stream_compute_integrity(algorithm, stream_cipher, result) != 0) {
return -1;
}
if (memcmp(result, expected, 4) != 0) {
LOG_E(OSA, "Mismatch found in integrity for algorithm %u,\n"
"\tgot %02x.%02x.%02x.%02x, expecting %02x.%02x.%02x.%02x\n",
algorithm, result[0], result[1], result[2], result[3], expected[0],
expected[1], expected[2], expected[3]);
return -1;
}
/* Integrity verification succeeded */
return 0;
}
......@@ -72,7 +72,7 @@ ifeq ($(ENABLE_DB), 1)
CFLAGS +=-I/usr/include/mysql -L/usr/lib/mysql -DENABLE_DB_STATS
DB_LDFLAGS = -lmysqlclient
endif
endif
endif
ifdef PRINT_STATS
CFLAGS += -DPRINT_STATS
......@@ -162,6 +162,25 @@ ifneq ($(USE_MME), R8)
UPDATE_RELEASE_9=1
endif
ifdef SECU
NETTLE_FOUND = $(shell if pkg-config --exists nettle; then echo "1" ; else echo "0"; fi)
OPENSSL_FOUND = $(shell if pkg-config --exists openssl; then echo "1" ; else echo "0"; fi)
ifeq ($(NETTLE_FOUND), 0)
@echo "Nettle library >= 2.5 is not installed on your system, continuing with security disabled"
SECU=0
else
ifeq ($(OPENSSL_FOUND), 0)
@echo "openssl library is not installed on your system, continuing with security disabled"
SECU=0
else
CFLAGS += -DENABLE_SECURITY
OSA_LDFLAGS += `pkg-config --libs nettle`
OSA_LDFLAGS += `pkg-config --libs openssl`
endif
endif
endif
include $(OPENAIR1_DIR)/PHY/Makefile.inc
include $(OPENAIR1_DIR)/SCHED/Makefile.inc
include $(OPENAIR2_DIR)/RRC/LITE/MESSAGES/Makefile.inc
......@@ -318,7 +337,8 @@ oaisim : $(ASN1_MSG_OBJS1) $(OBJ) oaisim.c $(LFDS_DIR)/bin/liblfds611.a
endif
@echo "Compiling oaisim.c ..."
@$(CC) -I$(TOP_DIR) $(L2_incl) $(UTIL_incl) -I$(ASN1_MSG_INC) $(S1AP_Incl) -o oaisim $(CFLAGS) $(EXTRA_CFLAGS) $^ \
-lm -lblas -lpthread -llapack_atlas -lforms -lxml2 -lX11 -lXpm -lrt $(LFDS_DIR)/bin/liblfds611.a $(PGM_LDFLAGS) $(DB_LDFLAGS)
-lm -lblas -lpthread -llapack_atlas -lforms -lxml2 -lX11 -lXpm -lrt \
$(LFDS_DIR)/bin/liblfds611.a $(PGM_LDFLAGS) $(DB_LDFLAGS) $(OSA_LDFLAGS)
ifeq ($(rrc_cellular_eNB),1)
mv oaisim oaisim_eNB
......
......@@ -939,6 +939,7 @@ int init_slot_isr(void)
oai_emulation.info.slot_sfd = sfd;
}
return 0;
}
void wait_for_slot_isr(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment