- 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
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
#include "platform_constants.h"
|
||||
#include "UTIL/LOG/vcd_signal_dumper.h"
|
||||
|
||||
#if defined(ENABLE_SECURITY)
|
||||
# include "UTIL/OSA/osa_defs.h"
|
||||
#endif
|
||||
|
||||
#define PDCP_DATA_REQ_DEBUG 0
|
||||
#define PDCP_DATA_IND_DEBUG 0
|
||||
|
||||
@@ -94,7 +98,7 @@ BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
|
||||
mem_block_t* pdcp_pdu = NULL;
|
||||
rlc_op_status_t rlc_status;
|
||||
|
||||
if ((pdcp->instanciated_instance == 0) && (mode != PDCP_TM)) {
|
||||
if ((pdcp->instanciated_instance == 0) && (mode != PDCP_TM)) {
|
||||
LOG_W(PDCP, "Instance is not configured, Ignoring SDU...\n");
|
||||
return FALSE;
|
||||
}
|
||||
@@ -178,16 +182,28 @@ BOOL pdcp_data_req(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
|
||||
free_mem_block(pdcp_pdu);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
LOG_D(PDCP, "Sequence number %d is assigned to current PDU\n", current_sn);
|
||||
|
||||
|
||||
/* Then append data... */
|
||||
memcpy(&pdcp_pdu->data[pdcp_header_len], sdu_buffer, sdu_buffer_size);
|
||||
|
||||
//For control plane data that are not integrity protected,
|
||||
// the MAC-I field is still present and should be padded with padding bits set to 0.
|
||||
// NOTE: user-plane data are never integrity protected
|
||||
for (i=0;i<pdcp_tailer_len;i++)
|
||||
pdcp_pdu->data[pdcp_header_len + sdu_buffer_size + i] = 0x00;// pdu_header.mac_i[i];
|
||||
|
||||
pdcp_pdu->data[pdcp_header_len + sdu_buffer_size + i] = 0x00;// pdu_header.mac_i[i];
|
||||
|
||||
#if defined(ENABLE_SECURITY)
|
||||
if ((pdcp->security_activated != 0) &&
|
||||
((pdcp->cipheringAlgorithm) != 0) &&
|
||||
((pdcp->integrityProtAlgorithm) != 0)) {
|
||||
pdcp_apply_security(pdcp, rb_id % NB_RB_MAX,
|
||||
pdcp_header_len, current_sn, pdcp_pdu->data,
|
||||
sdu_buffer_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Print octets of outgoing data in hexadecimal form */
|
||||
LOG_D(PDCP, "Following content with size %d will be sent over RLC (PDCP PDU header is the first two bytes)\n",
|
||||
pdcp_pdu_size);
|
||||
@@ -275,7 +291,8 @@ BOOL pdcp_data_ind(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
|
||||
u16 sequence_number;
|
||||
u8 payload_offset=0;
|
||||
|
||||
LOG_I(PDCP,"Data indication notification for PDCP entity with module ID %d and radio bearer ID %d rlc sdu size %d\n", module_id, rb_id, sdu_buffer_size);
|
||||
LOG_I(PDCP,"Data indication notification for PDCP entity with module "
|
||||
"ID %d and radio bearer ID %d rlc sdu size %d eNB_flag %d\n", module_id, rb_id, sdu_buffer_size, eNB_flag);
|
||||
|
||||
if (sdu_buffer_size == 0) {
|
||||
LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!");
|
||||
@@ -335,18 +352,13 @@ BOOL pdcp_data_ind(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
|
||||
}
|
||||
// SRB1/2: control-plane data
|
||||
if ( (rb_id % NB_RB_MAX) < DTCH ){
|
||||
/*new_sdu = get_free_mem_block(sdu_buffer_size - pdcp_header_len - pdcp_tailer_len);
|
||||
if (new_sdu) {
|
||||
memcpy(new_sdu->data,
|
||||
&sdu_buffer->data[pdcp_header_len],
|
||||
sdu_buffer_size - pdcp_header_len - pdcp_tailer_len);
|
||||
rrc_lite_data_ind(module_id,
|
||||
frame,
|
||||
eNB_flag,
|
||||
rb_id,
|
||||
sdu_buffer_size - pdcp_header_len - pdcp_tailer_len,
|
||||
new_sdu->data);
|
||||
}*/
|
||||
#if defined(ENABLE_SECURITY)
|
||||
if (pdcp->security_activated == 1) {
|
||||
pdcp_validate_security(pdcp, rb_id % NB_RB_MAX, pdcp_header_len,
|
||||
sequence_number, sdu_buffer->data,
|
||||
sdu_buffer_size - pdcp_tailer_len);
|
||||
}
|
||||
#endif
|
||||
//rrc_lite_data_ind(module_id, //Modified MW - L2 Interface
|
||||
pdcp_rrc_data_ind(module_id,
|
||||
frame,
|
||||
@@ -359,6 +371,13 @@ BOOL pdcp_data_ind(module_id_t module_id, u32_t frame, u8_t eNB_flag, rb_id_t rb
|
||||
return TRUE;
|
||||
}
|
||||
payload_offset=PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE;
|
||||
#if defined(ENABLE_SECURITY)
|
||||
if (pdcp->security_activated == 1) {
|
||||
pdcp_validate_security(pdcp, rb_id % NB_RB_MAX, pdcp_header_len,
|
||||
sequence_number, sdu_buffer->data,
|
||||
sdu_buffer_size - pdcp_tailer_len);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
payload_offset=0;
|
||||
}
|
||||
@@ -493,9 +512,6 @@ void
|
||||
// IP/NAS -> PDCP traffic : TX, read the pkt from the upper layer buffer
|
||||
pdcp_fifo_read_input_sdus(frame,eNB_flag);
|
||||
|
||||
// NAS -> PDCP traffic
|
||||
pdcp_fifo_read_input_sdus(frame,eNB_flag);
|
||||
|
||||
// PDCP -> NAS/IP traffic: RX
|
||||
pdcp_fifo_flush_sdus(frame,eNB_flag);
|
||||
|
||||
@@ -505,9 +521,13 @@ void
|
||||
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
|
||||
DRB_ToReleaseList_t* drb2release_list,
|
||||
u8 security_mode,
|
||||
u8 *kRRCenc,
|
||||
u8 *kRRCint,
|
||||
u8 *kUPenc
|
||||
#ifdef Rel10
|
||||
,PMCH_InfoList_r9_t* pmch_InfoList_r9
|
||||
,PMCH_InfoList_r9_t* pmch_InfoList_r9
|
||||
#endif
|
||||
){
|
||||
|
||||
@@ -537,7 +557,6 @@ BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u8_t eNB_flag
|
||||
(eNB_flag == 1)? "eNB": "UE", index);
|
||||
// srb2add_list does not define pdcp config, we use rlc info to setup the pdcp dcch0 and dcch1 channels
|
||||
|
||||
|
||||
if (srb2add_list != NULL) {
|
||||
for (cnt=0;cnt<srb2add_list->list.count;cnt++) {
|
||||
srb_id = srb2add_list->list.array[cnt]->srb_Identity;
|
||||
@@ -570,7 +589,10 @@ BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u8_t eNB_flag
|
||||
srb_sn,
|
||||
0, // drb_report
|
||||
0, // header compression
|
||||
0xff); //UNDEF_SECURITY_MODE
|
||||
security_mode,
|
||||
kRRCenc,
|
||||
kRRCint,
|
||||
kUPenc);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -659,7 +681,10 @@ BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u8_t eNB_flag
|
||||
drb_sn,
|
||||
drb_report,
|
||||
header_compression_profile,
|
||||
0xff);
|
||||
security_mode,
|
||||
kRRCenc,
|
||||
kRRCint,
|
||||
kUPenc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -681,7 +706,10 @@ BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u8_t eNB_flag
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0xff);
|
||||
security_mode,
|
||||
kRRCenc,
|
||||
kRRCint,
|
||||
kUPenc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -717,7 +745,10 @@ BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u8_t eNB_flag
|
||||
0, // set to deafult
|
||||
0,
|
||||
0,
|
||||
0xff);
|
||||
security_mode,
|
||||
kRRCenc,
|
||||
kRRCint,
|
||||
kUPenc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -727,18 +758,19 @@ BOOL rrc_pdcp_config_asn1_req (module_id_t module_id, u32_t frame, u8_t eNB_flag
|
||||
|
||||
}
|
||||
|
||||
|
||||
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 security_mode,
|
||||
u8 *kRRCenc,
|
||||
u8 *kRRCint,
|
||||
u8 *kUPenc){
|
||||
switch (action) {
|
||||
case ACTION_ADD:
|
||||
pdcp_array[module_id][lc_id].instanciated_instance = module_id + 1;
|
||||
pdcp_array[module_id][lc_id].is_ue = (eNB_flag == 0) ? 1 : 0;
|
||||
pdcp_array[module_id][lc_id].lcid = lc_id;
|
||||
pdcp_array[module_id][lc_id].header_compression_profile=header_compression_profile;
|
||||
pdcp_array[module_id][lc_id].cipheringAlgorithm=security_mode & 0x0f;
|
||||
pdcp_array[module_id][lc_id].integrityProtAlgorithm=(security_mode>>4) & 0xf;
|
||||
pdcp_array[module_id][lc_id].status_report = rb_report;
|
||||
if (rb_sn == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits)
|
||||
pdcp_array[module_id][lc_id].seq_num_size = 7;
|
||||
@@ -761,16 +793,24 @@ BOOL pdcp_config_req_asn1 (module_id_t module_id, u32 frame, u8_t eNB_flag, u16
|
||||
frame, lc_id, rb_id, pdcp_array[module_id][lc_id].seq_num_size,
|
||||
(rlc_mode == 1) ? "AM" : (rlc_mode == 2) ? "TM" : "UM");
|
||||
|
||||
/* Setup security */
|
||||
if (security_mode != 0xff) {
|
||||
pdcp_config_set_security(module_id, frame, eNB_flag, rb_id, lc_id, security_mode, kRRCenc, kRRCint, kUPenc);
|
||||
}
|
||||
|
||||
LOG_D(PDCP, "[MSC_NEW][FRAME %05d][PDCP][MOD %02d][RB %02d]\n", frame, module_id,rb_id);
|
||||
|
||||
break;
|
||||
case ACTION_MODIFY:
|
||||
pdcp_array[module_id][lc_id].header_compression_profile=header_compression_profile;
|
||||
pdcp_array[module_id][lc_id].cipheringAlgorithm=security_mode & 0x0f;
|
||||
pdcp_array[module_id][lc_id].integrityProtAlgorithm=(security_mode>>4) & 0xf;
|
||||
pdcp_array[module_id][lc_id].status_report = rb_report;
|
||||
pdcp_array[module_id][lc_id].rlc_mode = rlc_mode;
|
||||
|
||||
/* Setup security */
|
||||
if (security_mode != 0xff) {
|
||||
pdcp_config_set_security(module_id, frame, eNB_flag, rb_id, lc_id, security_mode, kRRCenc, kRRCint, kUPenc);
|
||||
}
|
||||
|
||||
if (rb_sn == PDCP_Config__rlc_UM__pdcp_SN_Size_len7bits)
|
||||
pdcp_array[module_id][lc_id].seq_num_size = 7;
|
||||
else if (rb_sn == PDCP_Config__rlc_UM__pdcp_SN_Size_len12bits)
|
||||
@@ -800,8 +840,21 @@ BOOL pdcp_config_req_asn1 (module_id_t module_id, u32 frame, u8_t eNB_flag, u16
|
||||
pdcp_array[module_id][lc_id].last_submitted_pdcp_rx_sn = 4095;
|
||||
pdcp_array[module_id][lc_id].seq_num_size = 0;
|
||||
pdcp_array[module_id][lc_id].first_missing_pdu = -1;
|
||||
pdcp_array[module_id][lc_id].security_activated = 0;
|
||||
|
||||
LOG_I(PDCP,"[%s %d] Config request : ACTION_REMOVE: Frame %d LCID %d RBID %d configured\n",
|
||||
(eNB_flag) ? "eNB" : "UE", module_id, frame, lc_id,rb_id);
|
||||
(eNB_flag) ? "eNB" : "UE", module_id, frame, lc_id, rb_id);
|
||||
/* Security keys */
|
||||
if (pdcp_array[module_id][lc_id].kUPenc != NULL) {
|
||||
free(pdcp_array[module_id][lc_id].kUPenc);
|
||||
}
|
||||
if (pdcp_array[module_id][lc_id].kRRCint != NULL) {
|
||||
free(pdcp_array[module_id][lc_id].kRRCint);
|
||||
}
|
||||
if (pdcp_array[module_id][lc_id].kRRCenc != NULL) {
|
||||
free(pdcp_array[module_id][lc_id].kRRCenc);
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case ACTION_MBMS_ADD:
|
||||
@@ -814,23 +867,37 @@ BOOL pdcp_config_req_asn1 (module_id_t module_id, u32 frame, u8_t eNB_flag, u16
|
||||
(eNB_flag == 1) ? "eNB" : "UE", module_id, frame, mch_id, lc_id, rb_id);
|
||||
break;
|
||||
case ACTION_SET_SECURITY_MODE:
|
||||
if ((security_mode >= 0 ) && (security_mode <=0x77)) {
|
||||
pdcp_array[module_id][lc_id].cipheringAlgorithm= security_mode & 0x0f;
|
||||
pdcp_array[module_id][lc_id].integrityProtAlgorithm = (security_mode>>4) & 0xf;
|
||||
LOG_D(PDCP,"[%s %d] Set security mode : ACTION_SET_SECURITY_MODE: Frame %d cipheringAlgorithm %d integrityProtAlgorithm %d\n",
|
||||
(eNB_flag) ? "eNB" : "UE", module_id, frame,
|
||||
pdcp_array[module_id][lc_id].cipheringAlgorithm,
|
||||
pdcp_array[module_id][lc_id].integrityProtAlgorithm );
|
||||
}else
|
||||
LOG_D(PDCP,"[%s %d] bad security mode %d", security_mode);
|
||||
break;
|
||||
pdcp_config_set_security(module_id, frame, eNB_flag, rb_id, lc_id, security_mode, kRRCenc, kRRCint, kUPenc);
|
||||
break;
|
||||
default:
|
||||
LOG_W(PDCP,"unknown action %d for the config request\n",action);
|
||||
break;
|
||||
LOG_W(PDCP,"unknown action %d for the config request\n",action);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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 ((security_mode >= 0) && (security_mode <= 0x77)) {
|
||||
pdcp_array[module_id][lc_id].cipheringAlgorithm = security_mode & 0x0f;
|
||||
pdcp_array[module_id][lc_id].integrityProtAlgorithm = (security_mode>>4) & 0xf;
|
||||
LOG_D(PDCP,"[%s %d][RB %02d] Set security mode : ACTION_SET_SECURITY_MODE: "
|
||||
"Frame %d cipheringAlgorithm %d integrityProtAlgorithm %d\n",
|
||||
(eNB_flag) ? "eNB" : "UE", module_id, rb_id, frame,
|
||||
pdcp_array[module_id][lc_id].cipheringAlgorithm,
|
||||
pdcp_array[module_id][lc_id].integrityProtAlgorithm);
|
||||
pdcp_array[module_id][lc_id].kRRCenc = kRRCenc;
|
||||
pdcp_array[module_id][lc_id].kRRCint = kRRCint;
|
||||
pdcp_array[module_id][lc_id].kUPenc = kUPenc;
|
||||
|
||||
/* Activate security */
|
||||
pdcp_array[module_id][lc_id].security_activated = 1;
|
||||
} else {
|
||||
LOG_D(PDCP,"[%s %d] bad security mode %d", security_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void rrc_pdcp_config_req (module_id_t module_id, u32 frame, u8_t eNB_flag, u32 action, rb_id_t rb_id, u8 security_mode){
|
||||
|
||||
/*
|
||||
@@ -867,6 +934,7 @@ void rrc_pdcp_config_req (module_id_t module_id, u32 frame, u8_t eNB_flag, u32
|
||||
pdcp_array[module_id][rb_id%NB_RB_MAX].last_submitted_pdcp_rx_sn = 4095;
|
||||
pdcp_array[module_id][rb_id%NB_RB_MAX].seq_num_size = 0;
|
||||
pdcp_array[module_id][rb_id%NB_RB_MAX].first_missing_pdu = -1;
|
||||
pdcp_array[module_id][rb_id].security_activated = 0;
|
||||
LOG_D(PDCP,"[%s %d] Config request : ACTION_REMOVE: Frame %d radio bearer id %d configured\n",
|
||||
(eNB_flag) ? "eNB" : "UE", module_id, frame, rb_id);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
/*******************************************************************************
|
||||
|
||||
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
|
||||
|
||||
+80
-15
@@ -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,10 +115,30 @@ 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
|
||||
|
||||
+28
-1
@@ -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)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
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.
|
||||
@@ -0,0 +1,129 @@
|
||||
/*******************************************************************************
|
||||
|
||||
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_ */
|
||||
@@ -0,0 +1,26 @@
|
||||
#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_ */
|
||||
@@ -0,0 +1,113 @@
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
#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)
|
||||
|
||||
Reference in New Issue
Block a user