Moved PDCP configs to pdcp_config.h. Added `as_security_cfg_t` structure to hold access stratum keys.

Refactored PDCP, RRC and USIM accordingly.
master
Pedro Alvarez 5 years ago
parent dc8dca2a08
commit 96c82b3fc6

@ -22,7 +22,7 @@
#ifndef SRSLTE_RRC_ASN1_UTILS_H
#define SRSLTE_RRC_ASN1_UTILS_H
#include "srslte/common/interfaces_common.h"
#include "srslte/upper/pdcp_config.h"
#include "srslte/interfaces/rrc_interface_types.h"
#include "srslte/interfaces/sched_interface.h"

@ -62,112 +62,6 @@ public:
uint32_t lcid;
};
/***************************
* PDCP Config
**************************/
// LTE and NR common config
const uint8_t PDCP_SN_LEN_5 = 5;
const uint8_t PDCP_SN_LEN_7 = 7;
const uint8_t PDCP_SN_LEN_12 = 12;
const uint8_t PDCP_SN_LEN_18 = 18;
typedef enum { PDCP_RB_IS_SRB, PDCP_RB_IS_DRB } pdcp_rb_type_t;
// Taken from PDCP-Config (TS 38.331 version 15.2.1)
enum class pdcp_t_reordering_t {
ms0 = 0,
ms1 = 1,
ms2 = 2,
ms4 = 4,
ms5 = 5,
ms8 = 8,
ms10 = 10,
ms15 = 15,
ms20 = 20,
ms30 = 30,
ms40 = 40,
ms50 = 50,
ms60 = 60,
ms80 = 80,
ms100 = 100,
ms120 = 120,
ms140 = 140,
ms160 = 160,
ms180 = 180,
ms200 = 200,
ms220 = 220,
ms240 = 240,
ms260 = 260,
ms280 = 280,
ms300 = 300,
ms500 = 500,
ms750 = 750,
ms1000 = 1000,
ms1250 = 1250,
ms1500 = 1500,
ms1750 = 1750,
ms2000 = 2000,
ms2250 = 2250,
ms2500 = 2500,
ms2750 = 2750,
ms3000 = 3000
};
// Taken from PDCP-Config (TS 38.331 version 15.2.1)
enum class pdcp_discard_timer_t {
ms10 = 10,
ms20 = 20,
ms30 = 30,
ms40 = 40,
ms50 = 50,
ms60 = 60,
ms75 = 75,
ms100 = 100,
ms150 = 150,
ms200 = 200,
ms250 = 250,
ms300 = 300,
ms500 = 500,
ms750 = 750,
ms1500 = 1500,
infinity = 0
};
class pdcp_config_t
{
public:
pdcp_config_t(uint8_t bearer_id_,
pdcp_rb_type_t rb_type_,
security_direction_t tx_direction_,
security_direction_t rx_direction_,
uint8_t sn_len_,
pdcp_t_reordering_t t_reordering_,
pdcp_discard_timer_t discard_timer_) :
bearer_id(bearer_id_),
rb_type(rb_type_),
tx_direction(tx_direction_),
rx_direction(rx_direction_),
sn_len(sn_len_),
t_reordering(t_reordering_),
discard_timer(discard_timer_)
{
hdr_len_bytes = ceil((float)sn_len / 8);
}
uint8_t bearer_id = 1;
pdcp_rb_type_t rb_type = PDCP_RB_IS_DRB;
security_direction_t tx_direction = SECURITY_DIRECTION_DOWNLINK;
security_direction_t rx_direction = SECURITY_DIRECTION_UPLINK;
uint8_t sn_len = PDCP_SN_LEN_12;
uint8_t hdr_len_bytes = 2;
pdcp_t_reordering_t t_reordering = pdcp_t_reordering_t::ms500;
pdcp_discard_timer_t discard_timer = pdcp_discard_timer_t::infinity;
// TODO: Support the following configurations
// bool do_rohc;
};
class read_pdu_interface
{
public:

@ -61,6 +61,16 @@ typedef enum {
} security_direction_t;
static const char security_direction_text[INTEGRITY_ALGORITHM_ID_N_ITEMS][20] = {"Uplink", "Downlink"};
using as_key_t = std::array<uint8_t, 32>;
struct as_security_config_t {
as_key_t k_rrc_int;
as_key_t k_rrc_enc;
as_key_t k_up_int;
as_key_t k_up_enc;
INTEGRITY_ALGORITHM_ID_ENUM integ_algo;
CIPHERING_ALGORITHM_ID_ENUM cipher_algo;
};
/******************************************************************************
* Key Generation
*****************************************************************************/

@ -29,6 +29,7 @@
#include "srslte/common/security.h"
#include "srslte/interfaces/rrc_interface_types.h"
#include "srslte/interfaces/sched_interface.h"
#include "srslte/upper/pdcp_config.h"
#include <vector>
#ifndef SRSLTE_ENB_INTERFACES_H
@ -340,20 +341,14 @@ public:
class pdcp_interface_rrc
{
public:
virtual void reset(uint16_t rnti) = 0;
virtual void add_user(uint16_t rnti) = 0;
virtual void rem_user(uint16_t rnti) = 0;
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cnfg) = 0;
virtual void config_security(uint16_t rnti,
uint32_t lcid,
uint8_t* k_rrc_enc_,
uint8_t* k_rrc_int_,
uint8_t* k_up_enc_,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0;
virtual void enable_integrity(uint16_t rnti, uint32_t lcid) = 0;
virtual void enable_encryption(uint16_t rnti, uint32_t lcid) = 0;
virtual void reset(uint16_t rnti) = 0;
virtual void add_user(uint16_t rnti) = 0;
virtual void rem_user(uint16_t rnti) = 0;
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) = 0;
virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cnfg) = 0;
virtual void config_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg) = 0;
virtual void enable_integrity(uint16_t rnti, uint32_t lcid) = 0;
virtual void enable_encryption(uint16_t rnti, uint32_t lcid) = 0;
virtual bool
get_bearer_status(uint16_t rnti, uint32_t lcid, uint16_t* dlsn, uint16_t* dlhfn, uint16_t* ulsn, uint16_t* ulhfn) = 0;
};

@ -38,6 +38,7 @@
#include "srslte/common/security.h"
#include "srslte/common/stack_procedure.h"
#include "srslte/interfaces/rrc_interface_types.h"
#include "srslte/upper/pdcp_config.h"
#include "srslte/phy/channel/channel.h"
#include "srslte/phy/rf/rf.h"
#include "srslte/upper/pdcp_entity_base.h"
@ -73,23 +74,8 @@ public:
class usim_interface_rrc
{
public:
virtual void generate_as_keys(uint8_t* k_asme,
uint32_t count_ul,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
virtual void generate_as_keys_ho(uint32_t pci,
uint32_t earfcn,
int ncc,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
virtual void generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_security_config_t* sec_cfg) = 0;
virtual void generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg) = 0;
};
// GW interface for NAS
@ -234,17 +220,8 @@ public:
virtual void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) = 0;
virtual void add_bearer(uint32_t lcid, srslte::pdcp_config_t cnfg) = 0;
virtual void change_lcid(uint32_t old_lcid, uint32_t new_lcid) = 0;
virtual void config_security(uint32_t lcid,
uint8_t* k_rrc_enc_,
uint8_t* k_rrc_int_,
uint8_t* k_up_enc_,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0;
virtual void config_security_all(uint8_t* k_rrc_enc_,
uint8_t* k_rrc_int_,
uint8_t* k_up_enc_,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) = 0;
virtual void config_security(uint32_t lcid, srslte::as_security_config_t sec_cfg) = 0;
virtual void config_security_all(srslte::as_security_config_t sec_cfg) = 0;
virtual void enable_integrity(uint32_t lcid, srslte::srslte_direction_t direction) = 0;
virtual void enable_encryption(uint32_t lcid,
srslte::srslte_direction_t direction = srslte::srslte_direction_t::DIRECTION_TXRX) = 0;

@ -50,17 +50,8 @@ public:
void add_bearer_mrb(uint32_t lcid, pdcp_config_t cnfg);
void del_bearer(uint32_t lcid);
void change_lcid(uint32_t old_lcid, uint32_t new_lcid);
void config_security(uint32_t lcid,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
void config_security_all(uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
void config_security(uint32_t lcid, as_security_config_t sec_cfg);
void config_security_all(as_security_config_t sec_cfg);
void enable_integrity(uint32_t lcid, srslte_direction_t direction);
void enable_encryption(uint32_t lcid, srslte_direction_t direction);
bool get_bearer_status(uint32_t lcid, uint16_t* dlsn, uint16_t* dlhfn, uint16_t* ulsn, uint16_t* ulhfn);

@ -0,0 +1,143 @@
/*
* Copyright 2013-2020 Software Radio Systems Limited
*
* This file is part of srsLTE.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/******************************************************************************
* File: pdcp_config.h
* Description: Structures used for configuration of the PDCP entities
*****************************************************************************/
#ifndef SRSLTE_PDCP_CONFIG_H
#define SRSLTE_PDCP_CONFIG_H
#include "srslte/common/security.h"
#include <stdint.h>
namespace srslte {
/***************************
* PDCP Config
**************************/
// LTE and NR common config
const uint8_t PDCP_SN_LEN_5 = 5;
const uint8_t PDCP_SN_LEN_7 = 7;
const uint8_t PDCP_SN_LEN_12 = 12;
const uint8_t PDCP_SN_LEN_18 = 18;
typedef enum { PDCP_RB_IS_SRB, PDCP_RB_IS_DRB } pdcp_rb_type_t;
// Taken from PDCP-Config (TS 38.331 version 15.2.1)
enum class pdcp_t_reordering_t {
ms0 = 0,
ms1 = 1,
ms2 = 2,
ms4 = 4,
ms5 = 5,
ms8 = 8,
ms10 = 10,
ms15 = 15,
ms20 = 20,
ms30 = 30,
ms40 = 40,
ms50 = 50,
ms60 = 60,
ms80 = 80,
ms100 = 100,
ms120 = 120,
ms140 = 140,
ms160 = 160,
ms180 = 180,
ms200 = 200,
ms220 = 220,
ms240 = 240,
ms260 = 260,
ms280 = 280,
ms300 = 300,
ms500 = 500,
ms750 = 750,
ms1000 = 1000,
ms1250 = 1250,
ms1500 = 1500,
ms1750 = 1750,
ms2000 = 2000,
ms2250 = 2250,
ms2500 = 2500,
ms2750 = 2750,
ms3000 = 3000
};
// Taken from PDCP-Config (TS 38.331 version 15.2.1)
enum class pdcp_discard_timer_t {
ms10 = 10,
ms20 = 20,
ms30 = 30,
ms40 = 40,
ms50 = 50,
ms60 = 60,
ms75 = 75,
ms100 = 100,
ms150 = 150,
ms200 = 200,
ms250 = 250,
ms300 = 300,
ms500 = 500,
ms750 = 750,
ms1500 = 1500,
infinity = 0
};
class pdcp_config_t
{
public:
pdcp_config_t(uint8_t bearer_id_,
pdcp_rb_type_t rb_type_,
security_direction_t tx_direction_,
security_direction_t rx_direction_,
uint8_t sn_len_,
pdcp_t_reordering_t t_reordering_,
pdcp_discard_timer_t discard_timer_) :
bearer_id(bearer_id_),
rb_type(rb_type_),
tx_direction(tx_direction_),
rx_direction(rx_direction_),
sn_len(sn_len_),
t_reordering(t_reordering_),
discard_timer(discard_timer_)
{
hdr_len_bytes = ceil((float)sn_len / 8);
}
uint8_t bearer_id = 1;
pdcp_rb_type_t rb_type = PDCP_RB_IS_DRB;
security_direction_t tx_direction = SECURITY_DIRECTION_DOWNLINK;
security_direction_t rx_direction = SECURITY_DIRECTION_UPLINK;
uint8_t sn_len = PDCP_SN_LEN_12;
uint8_t hdr_len_bytes = 2;
pdcp_t_reordering_t t_reordering = pdcp_t_reordering_t::ms500;
pdcp_discard_timer_t discard_timer = pdcp_discard_timer_t::infinity;
// TODO: Support the following configurations
// bool do_rohc;
};
} // namespace srslte
#endif // SRSLTE_PDCP_CONFIG_H

@ -29,6 +29,7 @@
#include "srslte/common/security.h"
#include "srslte/common/threads.h"
#include "srslte/common/timers.h"
#include "srslte/upper/pdcp_config.h"
#include <mutex>
namespace srslte {
@ -97,12 +98,7 @@ public:
}
}
void config_security(uint8_t* k_rrc_enc_,
uint8_t* k_rrc_int_,
uint8_t* k_up_enc_,
uint8_t* k_up_int_, // NR Only, pass nullptr in LTE
CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo_);
void config_security(as_security_config_t sec_cfg_);
// GW/SDAP/RRC interface
void write_sdu(unique_byte_buffer_t sdu, bool blocking);
@ -134,13 +130,7 @@ protected:
std::mutex mutex;
uint8_t k_rrc_enc[32] = {};
uint8_t k_rrc_int[32] = {};
uint8_t k_up_enc[32] = {};
uint8_t k_up_int[32] = {};
CIPHERING_ALGORITHM_ID_ENUM cipher_algo = CIPHERING_ALGORITHM_ID_EEA0;
INTEGRITY_ALGORITHM_ID_ENUM integ_algo = INTEGRITY_ALGORITHM_ID_EIA0;
srslte::as_security_config_t sec_cfg = {};
// Security functions
void integrity_generate(uint8_t* msg, uint32_t msg_len, uint32_t count, uint8_t* mac);

@ -202,29 +202,20 @@ exit:
pthread_rwlock_unlock(&rwlock);
}
void pdcp::config_security(uint32_t lcid,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo)
void pdcp::config_security(uint32_t lcid, as_security_config_t sec_cfg)
{
pthread_rwlock_rdlock(&rwlock);
if (valid_lcid(lcid)) {
pdcp_array.at(lcid)->config_security(k_rrc_enc, k_rrc_int, k_up_enc, nullptr, cipher_algo, integ_algo);
pdcp_array.at(lcid)->config_security(sec_cfg);
}
pthread_rwlock_unlock(&rwlock);
}
void pdcp::config_security_all(uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo)
void pdcp::config_security_all(as_security_config_t sec_cfg)
{
pthread_rwlock_rdlock(&rwlock);
for (pdcp_map_t::iterator it = pdcp_array.begin(); it != pdcp_array.end(); ++it) {
it->second->config_security(k_rrc_enc, k_rrc_int, k_up_enc, nullptr, cipher_algo, integ_algo);
it->second->config_security(sec_cfg);
}
pthread_rwlock_unlock(&rwlock);
}

@ -30,32 +30,18 @@ pdcp_entity_base::pdcp_entity_base(srslte::timer_handler* timers_, srslte::log*
pdcp_entity_base::~pdcp_entity_base() {}
void pdcp_entity_base::config_security(uint8_t* k_rrc_enc_,
uint8_t* k_rrc_int_,
uint8_t* k_up_enc_,
uint8_t* k_up_int_,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo_)
void pdcp_entity_base::config_security(as_security_config_t sec_cfg_)
{
for (int i = 0; i < 32; i++) {
k_rrc_enc[i] = k_rrc_enc_[i];
k_rrc_int[i] = k_rrc_int_[i];
k_up_enc[i] = k_up_enc_[i];
if (k_up_int_ != nullptr) {
k_up_int[i] = k_up_int_[i];
}
}
cipher_algo = cipher_algo_;
integ_algo = integ_algo_;
sec_cfg = sec_cfg_;
log->info("Configuring security with %s and %s\n",
integrity_algorithm_id_text[integ_algo],
ciphering_algorithm_id_text[cipher_algo]);
integrity_algorithm_id_text[sec_cfg.integ_algo],
ciphering_algorithm_id_text[sec_cfg.cipher_algo]);
log->debug_hex(k_rrc_enc, 32, "K_rrc_enc");
log->debug_hex(k_up_enc, 32, "K_up_enc");
log->debug_hex(k_rrc_int, 32, "K_rrc_int");
log->debug_hex(k_up_int, 32, "K_up_int");
log->debug_hex(sec_cfg.k_rrc_enc.data(), 32, "K_rrc_enc");
log->debug_hex(sec_cfg.k_up_enc.data(), 32, "K_up_enc");
log->debug_hex(sec_cfg.k_rrc_int.data(), 32, "K_rrc_int");
log->debug_hex(sec_cfg.k_up_int.data(), 32, "K_up_int");
}
/****************************************************************************
@ -67,12 +53,12 @@ void pdcp_entity_base::integrity_generate(uint8_t* msg, uint32_t msg_len, uint32
// If control plane use RRC integrity key. If data use user plane key
if (is_srb()) {
k_int = k_rrc_int;
k_int = sec_cfg.k_rrc_int.data();
} else {
k_int = k_up_int;
k_int = sec_cfg.k_up_int.data();
}
switch (integ_algo) {
switch (sec_cfg.integ_algo) {
case INTEGRITY_ALGORITHM_ID_EIA0:
break;
case INTEGRITY_ALGORITHM_ID_128_EIA1:
@ -104,12 +90,12 @@ bool pdcp_entity_base::integrity_verify(uint8_t* msg, uint32_t msg_len, uint32_t
// If control plane use RRC integrity key. If data use user plane key
if (is_srb()) {
k_int = k_rrc_int;
k_int = sec_cfg.k_rrc_int.data();
} else {
k_int = k_up_int;
k_int = sec_cfg.k_up_int.data();
}
switch (integ_algo) {
switch (sec_cfg.integ_algo) {
case INTEGRITY_ALGORITHM_ID_EIA0:
break;
case INTEGRITY_ALGORITHM_ID_128_EIA1:
@ -131,7 +117,7 @@ bool pdcp_entity_base::integrity_verify(uint8_t* msg, uint32_t msg_len, uint32_t
cfg.rx_direction == SECURITY_DIRECTION_DOWNLINK ? "Downlink" : "Uplink");
log->debug_hex(msg, msg_len, "Integrity check input msg:");
if (integ_algo != INTEGRITY_ALGORITHM_ID_EIA0) {
if (sec_cfg.integ_algo != INTEGRITY_ALGORITHM_ID_EIA0) {
for (uint8_t i = 0; i < 4; i++) {
if (mac[i] != mac_exp[i]) {
log->error_hex(mac_exp, 4, "MAC mismatch (expected)");
@ -155,9 +141,9 @@ void pdcp_entity_base::cipher_encrypt(uint8_t* msg, uint32_t msg_len, uint32_t c
// If control plane use RRC encrytion key. If data use user plane key
if (is_srb()) {
k_enc = k_rrc_enc;
k_enc = sec_cfg.k_rrc_enc.data();
} else {
k_enc = k_up_enc;
k_enc = sec_cfg.k_up_enc.data();
}
log->debug("Cipher encrypt input: COUNT: %" PRIu32 ", Bearer ID: %d, Direction %s\n",
@ -166,7 +152,7 @@ void pdcp_entity_base::cipher_encrypt(uint8_t* msg, uint32_t msg_len, uint32_t c
cfg.tx_direction == SECURITY_DIRECTION_DOWNLINK ? "Downlink" : "Uplink");
log->debug_hex(msg, msg_len, "Cipher encrypt input msg");
switch (cipher_algo) {
switch (sec_cfg.cipher_algo) {
case CIPHERING_ALGORITHM_ID_EEA0:
break;
case CIPHERING_ALGORITHM_ID_128_EEA1:
@ -194,9 +180,9 @@ void pdcp_entity_base::cipher_decrypt(uint8_t* ct, uint32_t ct_len, uint32_t cou
// If control plane use RRC encrytion key. If data use user plane key
if (is_srb()) {
k_enc = k_rrc_enc;
k_enc = sec_cfg.k_rrc_enc.data();
} else {
k_enc = k_up_enc;
k_enc = sec_cfg.k_up_enc.data();
}
log->debug("Cipher decrypt input: COUNT: %" PRIu32 ", Bearer ID: %d, Direction %s\n",
@ -205,7 +191,7 @@ void pdcp_entity_base::cipher_decrypt(uint8_t* ct, uint32_t ct_len, uint32_t cou
(cfg.rx_direction == SECURITY_DIRECTION_DOWNLINK) ? "Downlink" : "Uplink");
log->debug_hex(ct, ct_len, "Cipher decrypt input msg");
switch (cipher_algo) {
switch (sec_cfg.cipher_algo) {
case CIPHERING_ALGORITHM_ID_EEA0:
break;
case CIPHERING_ALGORITHM_ID_128_EEA1:

@ -112,16 +112,17 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, bool blocking)
write_data_header(sdu, tx_count);
// Append MAC (SRBs only)
uint8_t mac[4] = {};
if (integrity_direction == DIRECTION_TX || integrity_direction == DIRECTION_TXRX) {
bool do_integrity = integrity_direction == DIRECTION_TX || integrity_direction == DIRECTION_TXRX;
if (do_integrity && is_srb()) {
integrity_generate(sdu->msg, sdu->N_bytes, tx_count, mac);
}
// Append MAC-I
if (is_srb()) {
append_mac(sdu, mac);
}
if (encryption_direction == DIRECTION_TX || encryption_direction == DIRECTION_TXRX) {
cipher_encrypt(
&sdu->msg[cfg.hdr_len_bytes], sdu->N_bytes - cfg.hdr_len_bytes, tx_count, &sdu->msg[cfg.hdr_len_bytes]);

@ -22,6 +22,7 @@
#ifndef SRSLTE_PDCP_BASE_TEST_H
#define SRSLTE_PDCP_BASE_TEST_H
#include "srslte/upper/pdcp_config.h"
#include "srslte/common/buffer_pool.h"
#include "srslte/common/log_filter.h"
#include "srslte/common/security.h"
@ -36,18 +37,6 @@ int compare_two_packets(const srslte::unique_byte_buffer_t& msg1, const srslte::
return 0;
}
/*
* Definition of helpful structs for testing
*/
struct pdcp_security_cfg {
uint8_t* k_int_rrc;
uint8_t* k_enc_rrc;
uint8_t* k_int_up;
uint8_t* k_enc_up;
srslte::INTEGRITY_ALGORITHM_ID_ENUM int_algo;
srslte::CIPHERING_ALGORITHM_ID_ENUM enc_algo;
};
/*
* Dummy classes
*/

@ -43,13 +43,15 @@ struct pdcp_test_event_t {
* Constant definitions that are common to multiple tests
*/
// Encryption and Integrity Keys
uint8_t k_int[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31};
uint8_t k_enc[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31};
std::array<uint8_t, 32> k_int = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21,
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31};
std::array<uint8_t, 32> k_enc = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21,
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31};
// Security Configuration, common to all tests.
pdcp_security_cfg sec_cfg = {
srslte::as_security_config_t sec_cfg = {
k_int,
k_enc,
k_int,
@ -72,7 +74,7 @@ pdcp_lte_initial_state normal_init_state = {};
class pdcp_lte_test_helper
{
public:
pdcp_lte_test_helper(srslte::pdcp_config_t cfg, pdcp_security_cfg sec_cfg, srslte::log* log) :
pdcp_lte_test_helper(srslte::pdcp_config_t cfg, srslte::as_security_config_t sec_cfg, srslte::log* log) :
rlc(log),
rrc(log),
gw(log),
@ -80,8 +82,7 @@ public:
pdcp(&rlc, &rrc, &gw, &timers, log)
{
pdcp.init(0, cfg);
pdcp.config_security(
sec_cfg.k_enc_rrc, sec_cfg.k_int_rrc, sec_cfg.k_enc_up, sec_cfg.k_int_up, sec_cfg.enc_algo, sec_cfg.int_algo);
pdcp.config_security(sec_cfg);
pdcp.enable_integrity(srslte::DIRECTION_TXRX);
pdcp.enable_encryption(srslte::DIRECTION_TXRX);
}
@ -106,7 +107,7 @@ srslte::unique_byte_buffer_t gen_expected_pdu(const srslte::unique_byte_buffer_t
uint32_t count,
uint8_t pdcp_sn_len,
srslte::pdcp_rb_type_t rb_type,
pdcp_security_cfg sec_cfg,
srslte::as_security_config_t sec_cfg,
srslte::byte_buffer_pool* pool,
srslte::log* log)
{
@ -140,7 +141,7 @@ std::vector<pdcp_test_event_t> gen_expected_pdus_vector(const srslte::unique_byt
const std::vector<uint32_t>& tx_nexts,
uint8_t pdcp_sn_len,
srslte::pdcp_rb_type_t rb_type,
pdcp_security_cfg sec_cfg,
srslte::as_security_config_t sec_cfg,
srslte::byte_buffer_pool* pool,
srslte::log* log)
{

@ -43,13 +43,15 @@ struct pdcp_test_event_t {
* Constant definitions that are common to multiple tests
*/
// Encryption and Integrity Keys
uint8_t k_int[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31};
uint8_t k_enc[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
0x16, 0x17, 0x18, 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31};
std::array<uint8_t, 32> k_int = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21,
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31};
std::array<uint8_t, 32> k_enc = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20, 0x21,
0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30, 0x31};
// Security Configuration, common to all tests.
pdcp_security_cfg sec_cfg = {
srslte::as_security_config_t sec_cfg = {
k_int,
k_enc,
k_int,
@ -93,7 +95,7 @@ pdcp_initial_state near_wraparound_init_state = {.tx_next = 4294967295,
class pdcp_nr_test_helper
{
public:
pdcp_nr_test_helper(srslte::pdcp_config_t cfg, pdcp_security_cfg sec_cfg, srslte::log* log) :
pdcp_nr_test_helper(srslte::pdcp_config_t cfg, srslte::as_security_config_t sec_cfg, srslte::log* log) :
rlc(log),
rrc(log),
gw(log),
@ -101,8 +103,7 @@ public:
pdcp(&rlc, &rrc, &gw, &timers, log)
{
pdcp.init(0, cfg);
pdcp.config_security(
sec_cfg.k_enc_rrc, sec_cfg.k_int_rrc, sec_cfg.k_enc_up, sec_cfg.k_int_up, sec_cfg.enc_algo, sec_cfg.int_algo);
pdcp.config_security(sec_cfg);
pdcp.enable_integrity(srslte::DIRECTION_TXRX);
pdcp.enable_encryption(srslte::DIRECTION_TXRX);
}
@ -126,7 +127,7 @@ public:
srslte::unique_byte_buffer_t gen_expected_pdu(const srslte::unique_byte_buffer_t& in_sdu,
uint32_t count,
uint8_t pdcp_sn_len,
pdcp_security_cfg sec_cfg,
srslte::as_security_config_t sec_cfg,
srslte::byte_buffer_pool* pool,
srslte::log* log)
{
@ -159,7 +160,7 @@ srslte::unique_byte_buffer_t gen_expected_pdu(const srslte::unique_byte_buffer_t
std::vector<pdcp_test_event_t> gen_expected_pdus_vector(const srslte::unique_byte_buffer_t& in_sdu,
const std::vector<uint32_t>& tx_nexts,
uint8_t pdcp_sn_len,
pdcp_security_cfg sec_cfg,
srslte::as_security_config_t sec_cfg,
srslte::byte_buffer_pool* pool,
srslte::log* log)
{

@ -289,13 +289,7 @@ public:
std::map<uint32_t, asn1::rrc::drb_to_add_mod_s> drbs;
uint8_t k_enb[32]; // Provided by MME
uint8_t k_rrc_enc[32];
uint8_t k_rrc_int[32];
uint8_t k_up_enc[32];
uint8_t k_up_int[32]; // Not used: only for relay nodes (3GPP 33.401 Annex A.7)
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo;
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo;
srslte::as_security_config_t sec_cfg = {};
asn1::s1ap::ue_aggregate_maximum_bitrate_s bitrates;
asn1::s1ap::ue_security_cap_s security_capabilities;
@ -380,14 +374,7 @@ private:
void config_mac();
void parse_ul_dcch(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu);
void parse_ul_ccch(uint16_t rnti, srslte::unique_byte_buffer_t pdu);
void configure_security(uint16_t rnti,
uint32_t lcid,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
void configure_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg);
void enable_integrity(uint16_t rnti, uint32_t lcid);
void enable_encryption(uint16_t rnti, uint32_t lcid);

@ -48,13 +48,7 @@ public:
void rem_user(uint16_t rnti) override;
void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) override;
void add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cnfg) override;
void config_security(uint16_t rnti,
uint32_t lcid,
uint8_t* k_rrc_enc_,
uint8_t* k_rrc_int_,
uint8_t* k_up_enc_,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) override;
void config_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t cfg_sec) override;
void enable_integrity(uint16_t rnti, uint32_t lcid) override;
void enable_encryption(uint16_t rnti, uint32_t lcid) override;
bool get_bearer_status(uint16_t rnti, uint32_t lcid, uint16_t* dlsn, uint16_t* dlhfn, uint16_t* ulsn, uint16_t* ulhfn)

@ -957,17 +957,9 @@ void rrc::configure_mbsfn_sibs(sib_type2_s* sib2_, sib_type13_r9_s* sib13_)
mac->write_mcch(sib2_, sib13_, &mcch);
}
void rrc::configure_security(uint16_t rnti,
uint32_t lcid,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo)
void rrc::configure_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg)
{
// TODO: add k_up_enc, k_up_int support to PDCP
pdcp->config_security(rnti, lcid, k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo);
pdcp->config_security(rnti, lcid, sec_cfg);
}
void rrc::enable_integrity(uint16_t rnti, uint32_t lcid)
@ -1053,8 +1045,6 @@ rrc::ue::ue(rrc* outer_rrc, uint16_t rnti_, const sched_interface::ue_cfg_t& sch
{
activity_timer = outer_rrc->timers->get_unique_timer();
set_activity_timeout(MSG3_RX_TIMEOUT); // next UE response is Msg3
integ_algo = srslte::INTEGRITY_ALGORITHM_ID_EIA0;
cipher_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0;
mobility_handler.reset(new rrc_mobility(this));
// Configure
@ -1374,21 +1364,23 @@ void rrc::ue::set_security_key(const asn1::fixed_bitstring<256, false, true>& ke
// Selects security algorithms (cipher_algo and integ_algo) based on capabilities and config preferences
select_security_algorithms();
parent->rrc_log->info("Selected security algorithms EEA: EEA%d EIA: EIA%d\n", cipher_algo, integ_algo);
parent->rrc_log->info("Selected security algorithms EEA: EEA%d EIA: EIA%d\n", sec_cfg.cipher_algo, sec_cfg.integ_algo);
// Generate K_rrc_enc and K_rrc_int
srslte::security_generate_k_rrc(k_enb, cipher_algo, integ_algo, k_rrc_enc, k_rrc_int);
srslte::security_generate_k_rrc(
k_enb, sec_cfg.cipher_algo, sec_cfg.integ_algo, sec_cfg.k_rrc_enc.data(), sec_cfg.k_rrc_int.data());
// Generate K_up_enc and K_up_int
security_generate_k_up(k_enb, cipher_algo, integ_algo, k_up_enc, k_up_int);
security_generate_k_up(
k_enb, sec_cfg.cipher_algo, sec_cfg.integ_algo, sec_cfg.k_up_enc.data(), sec_cfg.k_up_int.data());
parent->configure_security(rnti, RB_ID_SRB1, k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo);
parent->configure_security(rnti, RB_ID_SRB1, sec_cfg);
parent->enable_integrity(rnti, RB_ID_SRB1);
parent->rrc_log->info_hex(k_rrc_enc, 32, "RRC Encryption Key (k_rrc_enc)");
parent->rrc_log->info_hex(k_rrc_int, 32, "RRC Integrity Key (k_rrc_int)");
parent->rrc_log->info_hex(k_up_enc, 32, "UP Encryption Key (k_up_enc)");
parent->rrc_log->info_hex(sec_cfg.k_rrc_enc.data(), 32, "RRC Encryption Key (k_rrc_enc)");
parent->rrc_log->info_hex(sec_cfg.k_rrc_int.data(), 32, "RRC Integrity Key (k_rrc_int)");
parent->rrc_log->info_hex(sec_cfg.k_up_enc.data(), 32, "UP Encryption Key (k_up_enc)");
}
bool rrc::ue::setup_erabs(const asn1::s1ap::erab_to_be_setup_list_ctxt_su_req_l& e)
@ -1966,7 +1958,7 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu)
// Configure SRB2 in PDCP
parent->pdcp->add_bearer(rnti, 2, srslte::make_srb_pdcp_config_t(2, false));
parent->pdcp->config_security(rnti, 2, k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo);
parent->pdcp->config_security(rnti, 2, sec_cfg);
parent->pdcp->enable_integrity(rnti, 2);
parent->pdcp->enable_encryption(rnti, 2);
@ -1982,7 +1974,7 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu)
}
}
parent->pdcp->add_bearer(rnti, 3, pdcp_cnfg_drb);
parent->pdcp->config_security(rnti, 3, k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo);
parent->pdcp->config_security(rnti, 3, sec_cfg);
parent->pdcp->enable_integrity(rnti, 3);
parent->pdcp->enable_encryption(rnti, 3);
// DRB1 has already been configured in GTPU through bearer setup
@ -2083,9 +2075,9 @@ void rrc::ue::send_security_mode_command()
// TODO: select these based on UE capabilities and preference order
comm->crit_exts.set_c1().set_security_mode_cmd_r8();
comm->crit_exts.c1().security_mode_cmd_r8().security_cfg_smc.security_algorithm_cfg.ciphering_algorithm =
(ciphering_algorithm_r12_e::options)cipher_algo;
(ciphering_algorithm_r12_e::options)sec_cfg.cipher_algo;
comm->crit_exts.c1().security_mode_cmd_r8().security_cfg_smc.security_algorithm_cfg.integrity_prot_algorithm =
(security_algorithm_cfg_s::integrity_prot_algorithm_e_::options)integ_algo;
(security_algorithm_cfg_s::integrity_prot_algorithm_e_::options)sec_cfg.integ_algo;
last_security_mode_cmd = comm->crit_exts.c1().security_mode_cmd_r8().security_cfg_smc.security_algorithm_cfg;
send_dl_dcch(&dl_dcch_msg);
@ -2136,15 +2128,15 @@ bool rrc::ue::select_security_algorithms()
// “all bits equal to 0” UE supports no other algorithm than EEA0,
// specification does not cover the case in which EEA0 is supported with other algorithms
// just assume that EEA0 is always supported even this can not be explicity signaled by S1AP
cipher_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0;
enc_algo_found = true;
sec_cfg.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0;
enc_algo_found = true;
parent->rrc_log->info("Selected EEA0 as RRC encryption algorithm\n");
break;
case srslte::CIPHERING_ALGORITHM_ID_128_EEA1:
// “first bit” 128-EEA1,
if (v.get(v.length() - srslte::CIPHERING_ALGORITHM_ID_128_EEA1)) {
cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA1;
enc_algo_found = true;
sec_cfg.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA1;
enc_algo_found = true;
parent->rrc_log->info("Selected EEA1 as RRC encryption algorithm\n");
break;
} else {
@ -2154,8 +2146,8 @@ bool rrc::ue::select_security_algorithms()
case srslte::CIPHERING_ALGORITHM_ID_128_EEA2:
// “second bit” 128-EEA2,
if (v.get(v.length() - srslte::CIPHERING_ALGORITHM_ID_128_EEA2)) {
cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA2;
enc_algo_found = true;
sec_cfg.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA2;
enc_algo_found = true;
parent->rrc_log->info("Selected EEA2 as RRC encryption algorithm\n");
break;
} else {
@ -2165,8 +2157,8 @@ bool rrc::ue::select_security_algorithms()
case srslte::CIPHERING_ALGORITHM_ID_128_EEA3:
// “third bit” 128-EEA3,
if (v.get(v.length() - srslte::CIPHERING_ALGORITHM_ID_128_EEA3)) {
cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA3;
enc_algo_found = true;
sec_cfg.cipher_algo = srslte::CIPHERING_ALGORITHM_ID_128_EEA3;
enc_algo_found = true;
parent->rrc_log->info("Selected EEA3 as RRC encryption algorithm\n");
break;
} else {
@ -2192,8 +2184,8 @@ bool rrc::ue::select_security_algorithms()
case srslte::INTEGRITY_ALGORITHM_ID_128_EIA1:
// “first bit” 128-EIA1,
if (v.get(v.length() - srslte::INTEGRITY_ALGORITHM_ID_128_EIA1)) {
integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA1;
integ_algo_found = true;
sec_cfg.integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA1;
integ_algo_found = true;
parent->rrc_log->info("Selected EIA1 as RRC integrity algorithm.\n");
} else {
parent->rrc_log->info("Failed to selected EIA1 as RRC encryption algorithm, due to unsupported algorithm\n");
@ -2202,8 +2194,8 @@ bool rrc::ue::select_security_algorithms()
case srslte::INTEGRITY_ALGORITHM_ID_128_EIA2:
// “second bit” 128-EIA2,
if (v.get(v.length() - srslte::INTEGRITY_ALGORITHM_ID_128_EIA2)) {
integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA2;
integ_algo_found = true;
sec_cfg.integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA2;
integ_algo_found = true;
parent->rrc_log->info("Selected EIA2 as RRC integrity algorithm.\n");
} else {
parent->rrc_log->info("Failed to selected EIA2 as RRC encryption algorithm, due to unsupported algorithm\n");
@ -2212,7 +2204,7 @@ bool rrc::ue::select_security_algorithms()
case srslte::INTEGRITY_ALGORITHM_ID_128_EIA3:
// “third bit” 128-EIA3,
if (v.get(v.length() - srslte::INTEGRITY_ALGORITHM_ID_128_EIA3)) {
integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA3;
sec_cfg.integ_algo = srslte::INTEGRITY_ALGORITHM_ID_128_EIA3;
integ_algo_found = true;
parent->rrc_log->info("Selected EIA3 as RRC integrity algorithm.\n");
} else {

@ -871,8 +871,8 @@ bool rrc::ue::rrc_mobility::start_ho_preparation(uint32_t target_eci,
rrc_details::compute_mac_i(rrc_ue->rnti,
rrc_enb->cfg.sib1.cell_access_related_info.cell_id.to_number(),
rrc_enb->cfg.cell_list.at(0).pci, // TODO: use actual PCI of source cell
rrc_ue->integ_algo,
rrc_ue->k_rrc_int));
rrc_ue->sec_cfg.integ_algo,
rrc_ue->sec_cfg.k_rrc_int.data()));
/*** pack HO Preparation Info into an RRC container buffer ***/
srslte::unique_byte_buffer_t buffer = srslte::allocate_unique_buffer(*pool);

@ -96,16 +96,10 @@ void pdcp::reset(uint16_t rnti)
}
}
void pdcp::config_security(uint16_t rnti,
uint32_t lcid,
uint8_t* k_rrc_enc_,
uint8_t* k_rrc_int_,
uint8_t* k_up_enc_,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_)
void pdcp::config_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg)
{
if (users.count(rnti)) {
users[rnti].pdcp->config_security(lcid, k_rrc_enc_, k_rrc_int_, k_up_enc_, cipher_algo_, integ_algo_);
users[rnti].pdcp->config_security(lcid, sec_cfg);
}
}

@ -63,15 +63,7 @@ public:
void rem_user(uint16_t rnti) override {}
void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) override {}
void add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cnfg) override {}
void config_security(uint16_t rnti,
uint32_t lcid,
uint8_t* k_rrc_enc_,
uint8_t* k_rrc_int_,
uint8_t* k_up_enc_,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo_) override
{
}
void config_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg_) override {}
void enable_integrity(uint16_t rnti, uint32_t lcid) override {}
void enable_encryption(uint16_t rnti, uint32_t lcid) override {}
bool get_bearer_status(uint16_t rnti, uint32_t lcid, uint16_t* dlsn, uint16_t* dlhfn, uint16_t* ulsn, uint16_t* ulhfn)

@ -401,13 +401,7 @@ private:
bool pending_mob_reconf = false;
asn1::rrc::rrc_conn_recfg_s mob_reconf = {};
uint8_t k_rrc_enc[32] = {};
uint8_t k_rrc_int[32] = {};
uint8_t k_up_enc[32] = {};
uint8_t k_up_int[32] = {}; // Not used: only for relay nodes (3GPP 33.401 Annex A.7)
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0;
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo = srslte::INTEGRITY_ALGORITHM_ID_EIA0;
srslte::as_security_config_t sec_cfg = {};
std::map<uint32_t, asn1::rrc::srb_to_add_mod_s> srbs;
std::map<uint32_t, asn1::rrc::drb_to_add_mod_s> drbs;

@ -82,24 +82,8 @@ public:
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
// RRC interface
void generate_as_keys(uint8_t* k_asme,
uint32_t count_ul,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
void generate_as_keys_ho(uint32_t pci,
uint32_t earfcn,
int ncc,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
void generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_security_config_t* sec_cfg);
void generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg);
private:
srslte::log* log = nullptr;

@ -61,24 +61,8 @@ public:
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
// RRC interface
void generate_as_keys(uint8_t* k_asme,
uint32_t count_ul,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
void generate_as_keys_ho(uint32_t pci,
uint32_t earfcn,
int ncc,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo);
void generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_security_config_t* sec_cfg);
void generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg);
private:
auth_result_t gen_auth_res_milenage(uint8_t* rand,

@ -84,24 +84,8 @@ public:
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
// RRC interface
virtual void generate_as_keys(uint8_t* k_asme,
uint32_t count_ul,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
virtual void generate_as_keys_ho(uint32_t pci,
uint32_t earfcn,
int ncc,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) = 0;
virtual void generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_security_config_t* sec_cfg) = 0;
virtual void generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg) = 0;
};
} // namespace srsue

@ -934,9 +934,9 @@ void rrc::send_con_restablish_request(reest_cause_e cause, uint16_t crnti, uint1
// Compute MAC-I
uint8_t mac_key[4] = {};
switch (integ_algo) {
switch (sec_cfg.integ_algo) {
case INTEGRITY_ALGORITHM_ID_128_EIA1:
security_128_eia1(&k_rrc_int[16],
security_128_eia1(&sec_cfg.k_rrc_int[16],
0xffffffff, // 32-bit all to ones
0x1f, // 5-bit all to ones
1, // 1-bit to one
@ -945,7 +945,7 @@ void rrc::send_con_restablish_request(reest_cause_e cause, uint16_t crnti, uint1
mac_key);
break;
case INTEGRITY_ALGORITHM_ID_128_EIA2:
security_128_eia2(&k_rrc_int[16],
security_128_eia2(&sec_cfg.k_rrc_int[16],
0xffffffff, // 32-bit all to ones
0x1f, // 5-bit all to ones
1, // 1-bit to one
@ -954,7 +954,7 @@ void rrc::send_con_restablish_request(reest_cause_e cause, uint16_t crnti, uint1
mac_key);
break;
case INTEGRITY_ALGORITHM_ID_128_EIA3:
security_128_eia3(&k_rrc_int[16],
security_128_eia3(&sec_cfg.k_rrc_int[16],
0xffffffff, // 32-bit all to ones
0x1f, // 5-bit all to ones
1, // 1-bit to one
@ -1130,27 +1130,19 @@ bool rrc::ho_prepare()
return false;
}
if (mob_reconf_r8->security_cfg_ho.handov_type.intra_lte().security_algorithm_cfg_present) {
cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM)mob_reconf_r8->security_cfg_ho.handov_type.intra_lte()
.security_algorithm_cfg.ciphering_algorithm.to_number();
integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM)mob_reconf_r8->security_cfg_ho.handov_type.intra_lte()
.security_algorithm_cfg.integrity_prot_algorithm.to_number();
sec_cfg.cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM)mob_reconf_r8->security_cfg_ho.handov_type.intra_lte()
.security_algorithm_cfg.ciphering_algorithm.to_number();
sec_cfg.integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM)mob_reconf_r8->security_cfg_ho.handov_type.intra_lte()
.security_algorithm_cfg.integrity_prot_algorithm.to_number();
rrc_log->info("Changed Ciphering to %s and Integrity to %s\n",
ciphering_algorithm_id_text[cipher_algo],
integrity_algorithm_id_text[integ_algo]);
ciphering_algorithm_id_text[sec_cfg.cipher_algo],
integrity_algorithm_id_text[sec_cfg.integ_algo]);
}
}
usim->generate_as_keys_ho(mob_ctrl_info->target_pci,
serving_cell->get_earfcn(),
ncc,
k_rrc_enc,
k_rrc_int,
k_up_enc,
k_up_int,
cipher_algo,
integ_algo);
pdcp->config_security_all(k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo);
usim->generate_as_keys_ho(mob_ctrl_info->target_pci, serving_cell->get_earfcn(), ncc, &sec_cfg);
pdcp->config_security_all(sec_cfg);
send_rrc_con_reconfig_complete();
}
return true;
@ -1940,34 +1932,33 @@ void rrc::parse_dl_dcch(uint32_t lcid, unique_byte_buffer_t pdu)
case dl_dcch_msg_type_c::c1_c_::types::security_mode_cmd:
transaction_id = c1->security_mode_cmd().rrc_transaction_id;
cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM)c1->security_mode_cmd()
.crit_exts.c1()
.security_mode_cmd_r8()
.security_cfg_smc.security_algorithm_cfg.ciphering_algorithm.value;
integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM)c1->security_mode_cmd()
.crit_exts.c1()
.security_mode_cmd_r8()
.security_cfg_smc.security_algorithm_cfg.integrity_prot_algorithm.value;
sec_cfg.cipher_algo = (CIPHERING_ALGORITHM_ID_ENUM)c1->security_mode_cmd()
.crit_exts.c1()
.security_mode_cmd_r8()
.security_cfg_smc.security_algorithm_cfg.ciphering_algorithm.value;
sec_cfg.integ_algo = (INTEGRITY_ALGORITHM_ID_ENUM)c1->security_mode_cmd()
.crit_exts.c1()
.security_mode_cmd_r8()
.security_cfg_smc.security_algorithm_cfg.integrity_prot_algorithm.value;
rrc_log->info("Received Security Mode Command eea: %s, eia: %s\n",
ciphering_algorithm_id_text[cipher_algo],
integrity_algorithm_id_text[integ_algo]);
ciphering_algorithm_id_text[sec_cfg.cipher_algo],
integrity_algorithm_id_text[sec_cfg.integ_algo]);
// Generate AS security keys
uint8_t k_asme[32];
nas->get_k_asme(k_asme, 32);
rrc_log->debug_hex(k_asme, 32, "UE K_asme");
rrc_log->debug("Generating K_enb with UL NAS COUNT: %d\n", nas->get_k_enb_count());
usim->generate_as_keys(
k_asme, nas->get_k_enb_count(), k_rrc_enc, k_rrc_int, k_up_enc, k_up_int, cipher_algo, integ_algo);
rrc_log->info_hex(k_rrc_enc, 32, "RRC encryption key - k_rrc_enc");
rrc_log->info_hex(k_rrc_int, 32, "RRC integrity key - k_rrc_int");
rrc_log->info_hex(k_up_enc, 32, "UP encryption key - k_up_enc");
usim->generate_as_keys(k_asme, nas->get_k_enb_count(), &sec_cfg);
rrc_log->info_hex(sec_cfg.k_rrc_enc.data(), 32, "RRC encryption key - k_rrc_enc");
rrc_log->info_hex(sec_cfg.k_rrc_int.data(), 32, "RRC integrity key - k_rrc_int");
rrc_log->info_hex(sec_cfg.k_up_enc.data(), 32, "UP encryption key - k_up_enc");
security_is_activated = true;
// Configure PDCP for security
pdcp->config_security(lcid, k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo);
pdcp->config_security(lcid, sec_cfg);
pdcp->enable_integrity(lcid, DIRECTION_TXRX);
send_security_mode_complete();
pdcp->enable_encryption(lcid, DIRECTION_TXRX);
@ -2631,16 +2622,8 @@ void rrc::handle_con_reest(rrc_conn_reest_s* setup)
// Update RRC Integrity keys
int ncc = setup->crit_exts.c1().rrc_conn_reest_r8().next_hop_chaining_count;
usim->generate_as_keys_ho(serving_cell->get_pci(),
serving_cell->get_earfcn(),
ncc,
k_rrc_enc,
k_rrc_int,
k_up_enc,
k_up_int,
cipher_algo,
integ_algo);
pdcp->config_security_all(k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo);
usim->generate_as_keys_ho(serving_cell->get_pci(), serving_cell->get_earfcn(), ncc, &sec_cfg);
pdcp->config_security_all(sec_cfg);
// Apply the Radio Resource configuration
apply_rr_config_dedicated(&setup->crit_exts.c1().rrc_conn_reest_r8().rr_cfg_ded);
@ -2659,7 +2642,7 @@ void rrc::add_srb(srb_to_add_mod_s* srb_cnfg)
// Setup PDCP
pdcp->add_bearer(srb_cnfg->srb_id, make_srb_pdcp_config_t(srb_cnfg->srb_id, true));
if (RB_ID_SRB2 == srb_cnfg->srb_id) {
pdcp->config_security(srb_cnfg->srb_id, k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo);
pdcp->config_security(srb_cnfg->srb_id, sec_cfg);
pdcp->enable_integrity(srb_cnfg->srb_id, DIRECTION_TXRX);
pdcp->enable_encryption(srb_cnfg->srb_id, DIRECTION_TXRX);
}
@ -2737,7 +2720,7 @@ void rrc::add_drb(drb_to_add_mod_s* drb_cnfg)
}
}
pdcp->add_bearer(lcid, pdcp_cfg);
pdcp->config_security(lcid, k_rrc_enc, k_rrc_int, k_up_enc, cipher_algo, integ_algo);
pdcp->config_security(lcid, sec_cfg);
pdcp->enable_encryption(lcid);
// Setup RLC

@ -264,14 +264,9 @@ void pcsc_usim::generate_nas_keys(uint8_t* k_asme,
RRC interface
*******************************************************************************/
void pcsc_usim::generate_as_keys(uint8_t* k_asme,
uint32_t count_ul,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo)
void pcsc_usim::generate_as_keys(uint8_t* k_asme,
uint32_t count_ul,
srslte::as_security_config_t* sec_cfg)
{
if (!initiated) {
ERROR("USIM not initiated!\n");
@ -284,23 +279,17 @@ void pcsc_usim::generate_as_keys(uint8_t* k_asme,
memcpy(this->k_asme, k_asme, 32);
// Generate K_rrc_enc and K_rrc_int
security_generate_k_rrc(k_enb, cipher_algo, integ_algo, k_rrc_enc, k_rrc_int);
security_generate_k_rrc(
k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_int.data());
// Generate K_up_enc and K_up_int
security_generate_k_up(k_enb, cipher_algo, integ_algo, k_up_enc, k_up_int);
security_generate_k_up(
k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_up_enc.data(), sec_cfg->k_up_int.data());
current_ncc = 0;
}
void pcsc_usim::generate_as_keys_ho(uint32_t pci,
uint32_t earfcn,
int ncc,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo)
void pcsc_usim::generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg)
{
if (!initiated) {
ERROR("USIM not initiated!\n");
@ -338,10 +327,12 @@ void pcsc_usim::generate_as_keys_ho(uint32_t pci,
memcpy(k_enb, k_enb_star, 32);
// Generate K_rrc_enc and K_rrc_int
security_generate_k_rrc(k_enb, cipher_algo, integ_algo, k_rrc_enc, k_rrc_int);
security_generate_k_rrc(
k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_int.data());
// Generate K_up_enc and K_up_int
security_generate_k_up(k_enb, cipher_algo, integ_algo, k_up_enc, k_up_int);
security_generate_k_up(
k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_up_enc.data(), sec_cfg->k_up_int.data());
}
/*******************************************************************************

@ -215,16 +215,8 @@ void usim::generate_nas_keys(uint8_t* k_asme,
RRC interface
*******************************************************************************/
void usim::generate_as_keys(uint8_t* k_asme,
uint32_t count_ul,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo)
void usim::generate_as_keys(uint8_t* k_asme, uint32_t count_ul, srslte::as_security_config_t *sec_cfg)
{
// Generate K_enb
security_generate_k_enb(k_asme, count_ul, k_enb);
@ -234,24 +226,18 @@ void usim::generate_as_keys(uint8_t* k_asme,
memcpy(k_enb_initial, k_enb, 32);
// Generate K_rrc_enc and K_rrc_int
security_generate_k_rrc(k_enb, cipher_algo, integ_algo, k_rrc_enc, k_rrc_int);
security_generate_k_rrc(
k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_int.data());
// Generate K_up_enc and K_up_int
security_generate_k_up(k_enb, cipher_algo, integ_algo, k_up_enc, k_up_int);
security_generate_k_up(
k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_up_enc.data(), sec_cfg->k_up_int.data());
current_ncc = 0;
is_first_ncc = true;
}
void usim::generate_as_keys_ho(uint32_t pci,
uint32_t earfcn,
int ncc,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int,
uint8_t* k_up_enc,
uint8_t* k_up_int,
CIPHERING_ALGORITHM_ID_ENUM cipher_algo,
INTEGRITY_ALGORITHM_ID_ENUM integ_algo)
void usim::generate_as_keys_ho(uint32_t pci, uint32_t earfcn, int ncc, srslte::as_security_config_t* sec_cfg)
{
uint8_t* enb_star_key = k_enb;
@ -285,10 +271,12 @@ void usim::generate_as_keys_ho(uint32_t pci,
memcpy(k_enb, k_enb_star, 32);
// Generate K_rrc_enc and K_rrc_int
security_generate_k_rrc(k_enb, cipher_algo, integ_algo, k_rrc_enc, k_rrc_int);
security_generate_k_rrc(
k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_int.data());
// Generate K_up_enc and K_up_int
security_generate_k_up(k_enb, cipher_algo, integ_algo, k_up_enc, k_up_int);
security_generate_k_up(
k_enb, sec_cfg->cipher_algo, sec_cfg->integ_algo, sec_cfg->k_up_enc.data(), sec_cfg->k_up_int.data());
}
/*******************************************************************************

@ -1037,11 +1037,12 @@ public:
const ttcn3_helpers::pdcp_count_map_t bearers)
{
// store security config for later use (i.e. new bearer added)
k_rrc_enc = k_rrc_enc_;
k_rrc_int = k_rrc_int_;
k_up_enc = k_up_enc_;
cipher_algo = cipher_algo_;
integ_algo = integ_algo_;
sec_cfg = {.k_rrc_int = k_rrc_int_,
.k_rrc_enc = k_rrc_enc_,
.k_up_int = {},
.k_up_enc = k_up_enc_,
.integ_algo = integ_algo_,
.cipher_algo = cipher_algo_};
// try to apply security config on bearers
pending_bearer_config = try_set_pdcp_security(bearers);
@ -1072,8 +1073,7 @@ public:
// make sure the current DL SN value match
if (lcid.dl_value == dl_sn) {
log.info("Setting AS security for LCID=%d in DL direction\n", lcid.rb_id);
pdcp.config_security(
lcid.rb_id, k_rrc_enc.data(), k_rrc_int.data(), k_up_enc.data(), cipher_algo, integ_algo);
pdcp.config_security(lcid.rb_id, sec_cfg);
pdcp.enable_integrity(lcid.rb_id, DIRECTION_TX);
pdcp.enable_encryption(lcid.rb_id, DIRECTION_TX);
lcid.dl_value_valid = false;
@ -1088,8 +1088,7 @@ public:
// Check UL count
if (lcid.ul_value == ul_sn) {
log.info("Setting AS security for LCID=%d in UL direction\n", lcid.rb_id);
pdcp.config_security(
lcid.rb_id, k_rrc_enc.data(), k_rrc_int.data(), k_up_enc.data(), cipher_algo, integ_algo);
pdcp.config_security(lcid.rb_id, sec_cfg);
pdcp.enable_integrity(lcid.rb_id, DIRECTION_RX);
pdcp.enable_encryption(lcid.rb_id, DIRECTION_RX);
lcid.ul_value_valid = false;
@ -1245,12 +1244,8 @@ private:
std::map<uint32_t, bool> bearer_follow_on_map; ///< Indicates if for a given LCID the follow_on_flag is set or not
// security config
ttcn3_helpers::pdcp_count_map_t pending_bearer_config; ///< List of bearers with pending security configuration
std::array<uint8_t, 32> k_rrc_enc;
std::array<uint8_t, 32> k_rrc_int;
std::array<uint8_t, 32> k_up_enc;
srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo = CIPHERING_ALGORITHM_ID_EEA0;
srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo = INTEGRITY_ALGORITHM_ID_EIA0;
ttcn3_helpers::pdcp_count_map_t pending_bearer_config; ///< List of bearers with pending security configuration
srslte::as_security_config_t sec_cfg;
std::vector<std::string> rb_id_vec =
{"SRB0", "SRB1", "SRB2", "DRB1", "DRB2", "DRB3", "DRB4", "DRB5", "DRB6", "DRB7", "DRB8"};

Loading…
Cancel
Save