Continuing to split pdcp_entity into pdcp_entity_lte and pdcp_entity_nr

master
Pedro Alvarez 6 years ago committed by Andre Puschmann
parent 005d03cb1a
commit bd91678d98

@ -90,7 +90,8 @@ protected:
bool do_integrity = false; bool do_integrity = false;
bool do_encryption = false; bool do_encryption = false;
private: std::mutex mutex;
uint8_t k_rrc_enc[32] = {}; uint8_t k_rrc_enc[32] = {};
uint8_t k_rrc_int[32] = {}; uint8_t k_rrc_int[32] = {};
uint8_t k_up_enc[32] = {}; uint8_t k_up_enc[32] = {};
@ -99,7 +100,6 @@ private:
CIPHERING_ALGORITHM_ID_ENUM cipher_algo = CIPHERING_ALGORITHM_ID_EEA0; CIPHERING_ALGORITHM_ID_ENUM cipher_algo = CIPHERING_ALGORITHM_ID_EEA0;
INTEGRITY_ALGORITHM_ID_ENUM integ_algo = INTEGRITY_ALGORITHM_ID_EIA0; INTEGRITY_ALGORITHM_ID_ENUM integ_algo = INTEGRITY_ALGORITHM_ID_EIA0;
std::mutex mutex;
void integrity_generate( void integrity_generate(
uint8_t* msg, uint32_t msg_len, uint32_t count, uint32_t bearer_id, uint32_t direction, uint8_t* mac); uint8_t* msg, uint32_t msg_len, uint32_t count, uint32_t bearer_id, uint32_t direction, uint8_t* mac);

@ -114,34 +114,36 @@ void pdcp_entity_lte::write_sdu(unique_byte_buffer_t sdu, bool blocking)
rrc->get_rb_name(lcid).c_str(), tx_count, rrc->get_rb_name(lcid).c_str(), tx_count,
(do_integrity) ? "true" : "false", (do_encryption) ? "true" : "false"); (do_integrity) ? "true" : "false", (do_encryption) ? "true" : "false");
pthread_mutex_lock(&mutex); mutex.lock();
if (cfg.is_control) { if (cfg.is_control) {
pdcp_pack_control_pdu(tx_count, sdu.get()); pdcp_pack_control_pdu(tx_count, sdu.get());
if(do_integrity) { if (do_integrity) {
integrity_generate(sdu->msg, integrity_generate(
sdu->N_bytes-4, sdu->msg, sdu->N_bytes - 4, tx_count, cfg.bearer_id, cfg.direction, &sdu->msg[sdu->N_bytes - 4]);
&sdu->msg[sdu->N_bytes-4]);
} }
} }
if (cfg.is_data) { if (cfg.is_data) {
if(12 == cfg.sn_len) { if (12 == cfg.sn_len) {
pdcp_pack_data_pdu_long_sn(tx_count, sdu.get()); pdcp_pack_data_pdu_long_sn(tx_count, sdu.get());
} else { } else {
pdcp_pack_data_pdu_short_sn(tx_count, sdu.get()); pdcp_pack_data_pdu_short_sn(tx_count, sdu.get());
} }
} }
if(do_encryption) { if (do_encryption) {
cipher_encrypt(&sdu->msg[sn_len_bytes], cipher_encrypt(&sdu->msg[sn_len_bytes],
sdu->N_bytes-sn_len_bytes, sdu->N_bytes - sn_len_bytes,
tx_count,
cfg.bearer_id,
cfg.direction,
&sdu->msg[sn_len_bytes]); &sdu->msg[sn_len_bytes]);
log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU (encrypted)", rrc->get_rb_name(lcid).c_str()); log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU (encrypted)", rrc->get_rb_name(lcid).c_str());
} }
tx_count++; tx_count++;
pthread_mutex_unlock(&mutex); mutex.unlock();
rlc->write_sdu(lcid, std::move(sdu), blocking); rlc->write_sdu(lcid, std::move(sdu), blocking);
} }
@ -162,7 +164,7 @@ void pdcp_entity_lte::write_pdu(unique_byte_buffer_t pdu)
return; return;
} }
pthread_mutex_lock(&mutex); mutex.lock();
if (cfg.is_data) { if (cfg.is_data) {
// Handle DRB messages // Handle DRB messages
@ -177,12 +179,18 @@ void pdcp_entity_lte::write_pdu(unique_byte_buffer_t pdu)
if (cfg.is_control) { if (cfg.is_control) {
uint32_t sn = *pdu->msg & 0x1F; uint32_t sn = *pdu->msg & 0x1F;
if (do_encryption) { if (do_encryption) {
cipher_decrypt(&pdu->msg[sn_len_bytes], sn, pdu->N_bytes - sn_len_bytes, &(pdu->msg[sn_len_bytes])); cipher_decrypt(&pdu->msg[sn_len_bytes],
pdu->N_bytes - sn_len_bytes,
sn,
cfg.bearer_id,
cfg.direction,
&(pdu->msg[sn_len_bytes]));
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str()); log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str());
} }
if (do_integrity) { if (do_integrity) {
if (not integrity_verify(pdu->msg, sn, pdu->N_bytes - 4, &(pdu->msg[pdu->N_bytes - 4]))) { if (not integrity_verify(
pdu->msg, pdu->N_bytes - 4, sn, cfg.bearer_id, cfg.direction, &(pdu->msg[pdu->N_bytes - 4]))) {
log->error_hex(pdu->msg, pdu->N_bytes, "%s Dropping PDU", rrc->get_rb_name(lcid).c_str()); log->error_hex(pdu->msg, pdu->N_bytes, "%s Dropping PDU", rrc->get_rb_name(lcid).c_str());
goto exit; goto exit;
} }
@ -196,7 +204,7 @@ void pdcp_entity_lte::write_pdu(unique_byte_buffer_t pdu)
} }
exit: exit:
rx_count++; rx_count++;
pthread_mutex_unlock(&mutex); mutex.unlock();
} }
/**************************************************************************** /****************************************************************************

@ -24,9 +24,9 @@
namespace srslte { namespace srslte {
pdcp_entity::pdcp_entity() {} pdcp_entity_nr::pdcp_entity_nr() {}
pdcp_entity::~pdcp_entity() {} pdcp_entity_nr::~pdcp_entity_nr() {}
void pdcp_entity_nr::init(srsue::rlc_interface_pdcp* rlc_, void pdcp_entity_nr::init(srsue::rlc_interface_pdcp* rlc_,
srsue::rrc_interface_pdcp* rrc_, srsue::rrc_interface_pdcp* rrc_,
@ -69,7 +69,7 @@ void pdcp_entity_nr::init(srsue::rlc_interface_pdcp* rlc_,
} }
// Reestablishment procedure: 36.323 5.2 // Reestablishment procedure: 36.323 5.2
void pdcp_entity::reestablish() void pdcp_entity_nr::reestablish()
{ {
log->info("Re-establish %s with bearer ID: %d\n", rrc->get_rb_name(lcid).c_str(), cfg.bearer_id); log->info("Re-establish %s with bearer ID: %d\n", rrc->get_rb_name(lcid).c_str(), cfg.bearer_id);
// For SRBs // For SRBs
@ -96,7 +96,7 @@ void pdcp_entity::reestablish()
} }
// Used to stop/pause the entity (called on RRC conn release) // Used to stop/pause the entity (called on RRC conn release)
void pdcp_entity::reset() void pdcp_entity_nr::reset()
{ {
active = false; active = false;
if (log) { if (log) {
@ -104,13 +104,8 @@ void pdcp_entity::reset()
} }
} }
bool pdcp_entity::is_active()
{
return active;
}
// SDAP/RRC interface // SDAP/RRC interface
void pdcp_entity::write_sdu(unique_byte_buffer_t sdu, bool blocking) void pdcp_entity_nr::write_sdu(unique_byte_buffer_t sdu, bool blocking)
{ {
log->info_hex(sdu->msg, sdu->N_bytes, log->info_hex(sdu->msg, sdu->N_bytes,
"TX %s SDU, SN: %d, do_integrity = %s, do_encryption = %s", "TX %s SDU, SN: %d, do_integrity = %s, do_encryption = %s",
@ -149,34 +144,8 @@ void pdcp_entity::write_sdu(unique_byte_buffer_t sdu, bool blocking)
rlc->write_sdu(lcid, std::move(sdu), blocking); rlc->write_sdu(lcid, std::move(sdu), blocking);
} }
void pdcp_entity::config_security(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_)
{
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];
}
cipher_algo = cipher_algo_;
integ_algo = integ_algo_;
}
void pdcp_entity::enable_integrity()
{
do_integrity = true;
}
void pdcp_entity::enable_encryption()
{
do_encryption = true;
}
// RLC interface // RLC interface
void pdcp_entity::write_pdu(unique_byte_buffer_t pdu) void pdcp_entity_nr::write_pdu(unique_byte_buffer_t pdu)
{ {
log->info_hex(pdu->msg, log->info_hex(pdu->msg,
pdu->N_bytes, pdu->N_bytes,
@ -242,7 +211,7 @@ exit:
* Ref: 3GPP TS 36.323 v10.1.0 Section 5.1.2 * Ref: 3GPP TS 36.323 v10.1.0 Section 5.1.2
***************************************************************************/ ***************************************************************************/
// DRBs mapped on RLC UM (5.1.2.1.3) // DRBs mapped on RLC UM (5.1.2.1.3)
void pdcp_entity::handle_um_drb_pdu(const srslte::unique_byte_buffer_t &pdu) void pdcp_entity_nr::handle_um_drb_pdu(const srslte::unique_byte_buffer_t &pdu)
{ {
uint32_t sn; uint32_t sn;
if (12 == cfg.sn_len) { if (12 == cfg.sn_len) {
@ -272,7 +241,7 @@ void pdcp_entity::handle_um_drb_pdu(const srslte::unique_byte_buffer_t &pdu)
} }
// DRBs mapped on RLC AM, without re-ordering (5.1.2.1.2) // DRBs mapped on RLC AM, without re-ordering (5.1.2.1.2)
void pdcp_entity::handle_am_drb_pdu(const srslte::unique_byte_buffer_t &pdu) void pdcp_entity_nr::handle_am_drb_pdu(const srslte::unique_byte_buffer_t &pdu)
{ {
uint32_t sn, count; uint32_t sn, count;
pdcp_unpack_data_pdu_long_sn(pdu.get(), &sn); pdcp_unpack_data_pdu_long_sn(pdu.get(), &sn);
@ -331,206 +300,6 @@ void pdcp_entity::handle_am_drb_pdu(const srslte::unique_byte_buffer_t &pdu)
/**************************************************************************** /****************************************************************************
* Security functions * Security functions
***************************************************************************/ ***************************************************************************/
void pdcp_entity::integrity_generate( uint8_t *msg,
uint32_t msg_len,
uint8_t *mac)
{
switch(integ_algo)
{
case INTEGRITY_ALGORITHM_ID_EIA0:
break;
case INTEGRITY_ALGORITHM_ID_128_EIA1:
security_128_eia1(&k_rrc_int[16],
tx_count,
cfg.bearer_id - 1,
cfg.direction,
msg,
msg_len,
mac);
break;
case INTEGRITY_ALGORITHM_ID_128_EIA2:
security_128_eia2(&k_rrc_int[16],
tx_count,
cfg.bearer_id - 1,
cfg.direction,
msg,
msg_len,
mac);
break;
default:
break;
}
log->debug("Integrity gen input:\n");
log->debug_hex(&k_rrc_int[16], 16, " K_rrc_int");
log->debug(" Local count: %d\n", tx_count);
log->debug(" Bearer ID: %d\n", cfg.bearer_id);
log->debug(" Direction: %s\n", (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? "Downlink" : "Uplink");
log->debug_hex(msg, msg_len, " Message");
log->debug_hex(mac, 4, "MAC (generated)");
}
bool pdcp_entity::integrity_verify(uint8_t *msg,
uint32_t count,
uint32_t msg_len,
uint8_t *mac)
{
uint8_t mac_exp[4] = {0x00};
uint8_t i = 0;
bool isValid = true;
switch(integ_algo)
{
case INTEGRITY_ALGORITHM_ID_EIA0:
break;
case INTEGRITY_ALGORITHM_ID_128_EIA1:
security_128_eia1(&k_rrc_int[16],
count,
cfg.bearer_id - 1,
(cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK),
msg,
msg_len,
mac_exp);
break;
case INTEGRITY_ALGORITHM_ID_128_EIA2:
security_128_eia2(&k_rrc_int[16],
count,
cfg.bearer_id - 1,
(cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK),
msg,
msg_len,
mac_exp);
break;
default:
break;
}
log->debug("Integrity check input:\n");
log->debug_hex(&k_rrc_int[16], 16, " K_rrc_int");
log->debug(" Local count: %d\n", count);
log->debug(" Bearer ID: %d\n", cfg.bearer_id);
log->debug(" Direction: %s\n", (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? "Uplink" : "Downlink");
log->debug_hex(msg, msg_len, " Message");
switch(integ_algo)
{
case INTEGRITY_ALGORITHM_ID_EIA0:
break;
case INTEGRITY_ALGORITHM_ID_128_EIA1: // Intentional fall-through
case INTEGRITY_ALGORITHM_ID_128_EIA2:
for(i=0; i<4; i++){
if(mac[i] != mac_exp[i]){
log->error_hex(mac_exp, 4, "MAC mismatch (expected)");
log->error_hex(mac, 4, "MAC mismatch (found)");
isValid = false;
break;
}
}
if (isValid){
log->info_hex(mac_exp, 4, "MAC match");
}
break;
default:
break;
}
return isValid;
}
void pdcp_entity::cipher_encrypt(uint8_t *msg,
uint32_t msg_len,
uint8_t *ct)
{
byte_buffer_t ct_tmp;
uint8_t *k_enc;
// If control plane use RRC encrytion key. If data use user plane key
if (cfg.is_control) {
k_enc = k_rrc_enc;
} else {
k_enc = k_up_enc;
}
log->debug("Cipher encrypt input:\n");
log->debug_hex(&k_enc[16], 16, " K_enc");
log->debug(" Local count: %d\n", tx_count);
log->debug(" TX HFN: %d COUNT %d\n", (tx_count >> cfg.sn_len), (tx_count << (32-cfg.sn_len)) >> (32-cfg.sn_len));
log->debug(" Bearer ID: %d\n", cfg.bearer_id);
log->debug(" Direction: %s\n", (cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? "Downlink" : "Uplink");
switch(cipher_algo)
{
case CIPHERING_ALGORITHM_ID_EEA0:
break;
case CIPHERING_ALGORITHM_ID_128_EEA1:
security_128_eea1(&(k_enc[16]),
tx_count,
cfg.bearer_id - 1,
cfg.direction,
msg,
msg_len,
ct_tmp.msg);
memcpy(ct, ct_tmp.msg, msg_len);
break;
case CIPHERING_ALGORITHM_ID_128_EEA2:
security_128_eea2(&(k_enc[16]),
tx_count,
cfg.bearer_id - 1,
cfg.direction,
msg,
msg_len,
ct_tmp.msg);
memcpy(ct, ct_tmp.msg, msg_len);
break;
default:
break;
}
}
void pdcp_entity::cipher_decrypt(uint8_t *ct,
uint32_t count,
uint32_t ct_len,
uint8_t *msg)
{
byte_buffer_t msg_tmp;
uint8_t *k_enc;
// If control plane use RRC encrytion key. If data use user plane key
if (cfg.is_control) {
k_enc = k_rrc_enc;
} else {
k_enc = k_up_enc;
}
switch(cipher_algo)
{
case CIPHERING_ALGORITHM_ID_EEA0:
break;
case CIPHERING_ALGORITHM_ID_128_EEA1:
security_128_eea1(&(k_enc[16]),
count,
cfg.bearer_id - 1,
(cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK),
ct,
ct_len,
msg_tmp.msg);
memcpy(msg, msg_tmp.msg, ct_len);
break;
case CIPHERING_ALGORITHM_ID_128_EEA2:
security_128_eea2(&(k_enc[16]),
count,
cfg.bearer_id - 1,
(cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK),
ct,
ct_len,
msg_tmp.msg);
memcpy(msg, msg_tmp.msg, ct_len);
break;
default:
break;
}
}
uint32_t pdcp_entity::get_dl_count() uint32_t pdcp_entity::get_dl_count()
{ {
return rx_count; return rx_count;
@ -546,7 +315,6 @@ uint32_t pdcp_entity::get_ul_count()
* Pack/Unpack helper functions * Pack/Unpack helper functions
* Ref: 3GPP TS 38.323 v15.2.0 * Ref: 3GPP TS 38.323 v15.2.0
***************************************************************************/ ***************************************************************************/
void pdcp_pack_control_pdu(uint32_t sn, byte_buffer_t *sdu) void pdcp_pack_control_pdu(uint32_t sn, byte_buffer_t *sdu)
{ {
// Make room and add header // Make room and add header

Loading…
Cancel
Save