|
|
|
@ -56,6 +56,12 @@ void pdcp_entity::init(srsue::rlc_interface_pdcp *rlc_,
|
|
|
|
|
rx_count = 0;
|
|
|
|
|
do_integrity = false;
|
|
|
|
|
do_encryption = false;
|
|
|
|
|
if(cfg.is_control) {
|
|
|
|
|
cfg.sn_len = 5;
|
|
|
|
|
sn_len_bytes = 1;
|
|
|
|
|
} else {
|
|
|
|
|
sn_len_bytes = (cfg.sn_len+7)/8;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
start(PDCP_THREAD_PRIO);
|
|
|
|
|
|
|
|
|
@ -87,46 +93,57 @@ bool pdcp_entity::is_active()
|
|
|
|
|
void pdcp_entity::write_sdu(byte_buffer_t *sdu)
|
|
|
|
|
{
|
|
|
|
|
log->info_hex(sdu->msg, sdu->N_bytes,
|
|
|
|
|
"TX %s SDU, do_integrity = %s, do_encryption = %s", get_rb_name(lcid),
|
|
|
|
|
"TX %s SDU, SN: %d, do_integrity = %s, do_encryption = %s",
|
|
|
|
|
get_rb_name(lcid), tx_count,
|
|
|
|
|
(do_integrity) ? "true" : "false", (do_encryption) ? "true" : "false");
|
|
|
|
|
|
|
|
|
|
if (cfg.is_control) {
|
|
|
|
|
pdcp_pack_control_pdu(tx_count, sdu);
|
|
|
|
|
if(do_integrity)
|
|
|
|
|
{
|
|
|
|
|
if(do_integrity) {
|
|
|
|
|
integrity_generate(sdu->msg,
|
|
|
|
|
sdu->N_bytes-4,
|
|
|
|
|
&sdu->msg[sdu->N_bytes-4]);
|
|
|
|
|
}
|
|
|
|
|
tx_count++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cfg.is_data) {
|
|
|
|
|
if(12 == cfg.sn_len) {
|
|
|
|
|
pdcp_pack_data_pdu_long_sn(tx_count++, sdu);
|
|
|
|
|
pdcp_pack_data_pdu_long_sn(tx_count, sdu);
|
|
|
|
|
} else {
|
|
|
|
|
pdcp_pack_data_pdu_short_sn(tx_count++, sdu);
|
|
|
|
|
pdcp_pack_data_pdu_short_sn(tx_count, sdu);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(do_encryption) {
|
|
|
|
|
cipher_encrypt(&sdu->msg[sn_len_bytes],
|
|
|
|
|
sdu->N_bytes-sn_len_bytes,
|
|
|
|
|
&sdu->msg[sn_len_bytes]);
|
|
|
|
|
log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU (encrypted)", get_rb_name(lcid));
|
|
|
|
|
}
|
|
|
|
|
tx_count++;
|
|
|
|
|
|
|
|
|
|
rlc->write_sdu(lcid, sdu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pdcp_entity::config_security(uint8_t *k_rrc_enc_,
|
|
|
|
|
uint8_t *k_rrc_int_,
|
|
|
|
|
void pdcp_entity::config_security(uint8_t *k_enc_,
|
|
|
|
|
uint8_t *k_int_,
|
|
|
|
|
CIPHERING_ALGORITHM_ID_ENUM cipher_algo_,
|
|
|
|
|
INTEGRITY_ALGORITHM_ID_ENUM integ_algo_)
|
|
|
|
|
{
|
|
|
|
|
do_integrity = true;
|
|
|
|
|
for(int i=0; i<32; i++)
|
|
|
|
|
{
|
|
|
|
|
k_rrc_enc[i] = k_rrc_enc_[i];
|
|
|
|
|
k_rrc_int[i] = k_rrc_int_[i];
|
|
|
|
|
k_enc[i] = k_enc_[i];
|
|
|
|
|
k_int[i] = k_int_[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;
|
|
|
|
@ -142,24 +159,26 @@ void pdcp_entity::integrity_generate( uint8_t *msg,
|
|
|
|
|
uint32_t msg_len,
|
|
|
|
|
uint8_t *mac)
|
|
|
|
|
{
|
|
|
|
|
uint8_t bearer;
|
|
|
|
|
|
|
|
|
|
switch(integ_algo)
|
|
|
|
|
{
|
|
|
|
|
case INTEGRITY_ALGORITHM_ID_EIA0:
|
|
|
|
|
break;
|
|
|
|
|
case INTEGRITY_ALGORITHM_ID_128_EIA1:
|
|
|
|
|
security_128_eia1(&k_rrc_int[16],
|
|
|
|
|
security_128_eia1(&k_int[16],
|
|
|
|
|
tx_count,
|
|
|
|
|
lcid-1,
|
|
|
|
|
get_bearer_id(lcid),
|
|
|
|
|
cfg.direction,
|
|
|
|
|
msg,
|
|
|
|
|
msg_len,
|
|
|
|
|
mac);
|
|
|
|
|
break;
|
|
|
|
|
case INTEGRITY_ALGORITHM_ID_128_EIA2:
|
|
|
|
|
security_128_eia2(&k_rrc_int[16],
|
|
|
|
|
security_128_eia2(&k_int[16],
|
|
|
|
|
tx_count,
|
|
|
|
|
lcid-1,
|
|
|
|
|
cfg.direction,
|
|
|
|
|
get_bearer_id(lcid),
|
|
|
|
|
cfg.direction,
|
|
|
|
|
msg,
|
|
|
|
|
msg_len,
|
|
|
|
|
mac);
|
|
|
|
@ -183,19 +202,19 @@ bool pdcp_entity::integrity_verify(uint8_t *msg,
|
|
|
|
|
case INTEGRITY_ALGORITHM_ID_EIA0:
|
|
|
|
|
break;
|
|
|
|
|
case INTEGRITY_ALGORITHM_ID_128_EIA1:
|
|
|
|
|
security_128_eia1(&k_rrc_int[16],
|
|
|
|
|
security_128_eia1(&k_int[16],
|
|
|
|
|
count,
|
|
|
|
|
lcid-1,
|
|
|
|
|
( cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK),
|
|
|
|
|
get_bearer_id(lcid),
|
|
|
|
|
(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],
|
|
|
|
|
security_128_eia2(&k_int[16],
|
|
|
|
|
count,
|
|
|
|
|
lcid-1,
|
|
|
|
|
( cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK),
|
|
|
|
|
get_bearer_id(lcid),
|
|
|
|
|
(cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK),
|
|
|
|
|
msg,
|
|
|
|
|
msg_len,
|
|
|
|
|
mac_exp);
|
|
|
|
@ -240,20 +259,20 @@ void pdcp_entity::cipher_encrypt(uint8_t *msg,
|
|
|
|
|
case CIPHERING_ALGORITHM_ID_EEA0:
|
|
|
|
|
break;
|
|
|
|
|
case CIPHERING_ALGORITHM_ID_128_EEA1:
|
|
|
|
|
security_128_eea1(&(k_rrc_enc[16]),
|
|
|
|
|
security_128_eea1(&(k_enc[16]),
|
|
|
|
|
tx_count,
|
|
|
|
|
lcid - 1,
|
|
|
|
|
cfg.direction,
|
|
|
|
|
get_bearer_id(lcid),
|
|
|
|
|
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_rrc_enc[16]),
|
|
|
|
|
security_128_eea2(&(k_enc[16]),
|
|
|
|
|
tx_count,
|
|
|
|
|
lcid - 1,
|
|
|
|
|
cfg.direction,
|
|
|
|
|
get_bearer_id(lcid),
|
|
|
|
|
cfg.direction,
|
|
|
|
|
msg,
|
|
|
|
|
msg_len,
|
|
|
|
|
ct_tmp.msg);
|
|
|
|
@ -275,19 +294,19 @@ void pdcp_entity::cipher_decrypt(uint8_t *ct,
|
|
|
|
|
case CIPHERING_ALGORITHM_ID_EEA0:
|
|
|
|
|
break;
|
|
|
|
|
case CIPHERING_ALGORITHM_ID_128_EEA1:
|
|
|
|
|
security_128_eea1(&(k_rrc_enc[16]),
|
|
|
|
|
security_128_eea1(&(k_enc[16]),
|
|
|
|
|
count,
|
|
|
|
|
lcid - 1,
|
|
|
|
|
( cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK),
|
|
|
|
|
get_bearer_id(lcid),
|
|
|
|
|
(cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK),
|
|
|
|
|
ct,
|
|
|
|
|
ct_len,
|
|
|
|
|
msg_tmp.msg);
|
|
|
|
|
break;
|
|
|
|
|
case CIPHERING_ALGORITHM_ID_128_EEA2:
|
|
|
|
|
security_128_eea2(&(k_rrc_enc[16]),
|
|
|
|
|
security_128_eea2(&(k_enc[16]),
|
|
|
|
|
count,
|
|
|
|
|
lcid - 1,
|
|
|
|
|
( cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK),
|
|
|
|
|
get_bearer_id(lcid),
|
|
|
|
|
(cfg.direction == SECURITY_DIRECTION_DOWNLINK) ? (SECURITY_DIRECTION_UPLINK) : (SECURITY_DIRECTION_DOWNLINK),
|
|
|
|
|
ct,
|
|
|
|
|
ct_len,
|
|
|
|
|
msg_tmp.msg);
|
|
|
|
@ -306,39 +325,35 @@ void pdcp_entity::run_thread()
|
|
|
|
|
|
|
|
|
|
while(running) {
|
|
|
|
|
rx_pdu_queue.read(&pdu);
|
|
|
|
|
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid));
|
|
|
|
|
|
|
|
|
|
// Handle SRB messages
|
|
|
|
|
switch(lcid)
|
|
|
|
|
{
|
|
|
|
|
case RB_ID_SRB0:
|
|
|
|
|
// Simply pass on to RRC
|
|
|
|
|
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid));
|
|
|
|
|
rrc->write_pdu(RB_ID_SRB0, pdu);
|
|
|
|
|
break;
|
|
|
|
|
case RB_ID_SRB1: // Intentional fall-through
|
|
|
|
|
case RB_ID_SRB2:
|
|
|
|
|
uint32_t sn;
|
|
|
|
|
|
|
|
|
|
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid));
|
|
|
|
|
|
|
|
|
|
if (do_encryption) {
|
|
|
|
|
cipher_decrypt(&(pdu->msg[1]),
|
|
|
|
|
pdu->msg[0],
|
|
|
|
|
pdu->N_bytes - 1,
|
|
|
|
|
&(pdu->msg[1]));
|
|
|
|
|
cipher_decrypt(&(pdu->msg[sn_len_bytes]),
|
|
|
|
|
rx_count,
|
|
|
|
|
pdu->N_bytes - sn_len_bytes,
|
|
|
|
|
&(pdu->msg[sn_len_bytes]));
|
|
|
|
|
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", get_rb_name(lcid));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (do_integrity) {
|
|
|
|
|
integrity_verify(pdu->msg,
|
|
|
|
|
pdu->msg[0],
|
|
|
|
|
rx_count,
|
|
|
|
|
pdu->N_bytes - 4,
|
|
|
|
|
&(pdu->msg[pdu->N_bytes - 4]));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pdcp_unpack_control_pdu(pdu, &sn);
|
|
|
|
|
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s SDU SN: %d",
|
|
|
|
|
get_rb_name(lcid), sn);
|
|
|
|
|
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", get_rb_name(lcid), sn);
|
|
|
|
|
rrc->write_pdu(lcid, pdu);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -347,18 +362,35 @@ void pdcp_entity::run_thread()
|
|
|
|
|
if(lcid >= RB_ID_DRB1)
|
|
|
|
|
{
|
|
|
|
|
uint32_t sn;
|
|
|
|
|
if (do_encryption) {
|
|
|
|
|
cipher_decrypt(&(pdu->msg[sn_len_bytes]),
|
|
|
|
|
rx_count,
|
|
|
|
|
pdu->N_bytes - sn_len_bytes,
|
|
|
|
|
&(pdu->msg[sn_len_bytes]));
|
|
|
|
|
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", get_rb_name(lcid));
|
|
|
|
|
}
|
|
|
|
|
if(12 == cfg.sn_len)
|
|
|
|
|
{
|
|
|
|
|
pdcp_unpack_data_pdu_long_sn(pdu, &sn);
|
|
|
|
|
} else {
|
|
|
|
|
pdcp_unpack_data_pdu_short_sn(pdu, &sn);
|
|
|
|
|
}
|
|
|
|
|
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU: %d", get_rb_name(lcid), sn);
|
|
|
|
|
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", get_rb_name(lcid), sn);
|
|
|
|
|
gw->write_pdu(lcid, pdu);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rx_count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t pdcp_entity::get_bearer_id(uint8_t lcid)
|
|
|
|
|
{
|
|
|
|
|
if(lcid <= RB_ID_SRB2) {
|
|
|
|
|
return lcid - 1;
|
|
|
|
|
} else {
|
|
|
|
|
return lcid - RB_ID_SRB2 - 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
|