Fix issue in integrity check in PDCP SRBs. Moved some helper functions to the pdcp base class

This commit is contained in:
Pedro Alvarez 2020-02-14 17:18:01 +00:00 committed by Andre Puschmann
parent 6508bd411f
commit fdd67c3865
5 changed files with 74 additions and 60 deletions

View File

@ -116,10 +116,15 @@ protected:
CIPHERING_ALGORITHM_ID_ENUM cipher_algo = CIPHERING_ALGORITHM_ID_EEA0;
INTEGRITY_ALGORITHM_ID_ENUM integ_algo = INTEGRITY_ALGORITHM_ID_EIA0;
// Security functions
void integrity_generate(uint8_t* msg, uint32_t msg_len, uint32_t count, uint8_t* mac);
bool integrity_verify(uint8_t* msg, uint32_t msg_len, uint32_t count, uint8_t* mac);
void cipher_encrypt(uint8_t* msg, uint32_t msg_len, uint32_t count, uint8_t* ct);
void cipher_decrypt(uint8_t* ct, uint32_t ct_len, uint32_t count, uint8_t* msg);
// Common packing functions
void extract_mac(const unique_byte_buffer_t& pdu, uint8_t* mac);
void append_mac(const unique_byte_buffer_t& sdu, uint8_t* mac);
};
inline uint32_t pdcp_entity_base::HFN(uint32_t count)

View File

@ -80,9 +80,9 @@ private:
uint32_t last_submitted_pdcp_rx_sn = 0;
uint32_t maximum_pdcp_sn = 0;
bool handle_srb_pdu(const srslte::unique_byte_buffer_t& pdu);
void handle_um_drb_pdu(const srslte::unique_byte_buffer_t& pdu);
void handle_am_drb_pdu(const srslte::unique_byte_buffer_t& pdu);
void handle_srb_pdu(srslte::unique_byte_buffer_t pdu);
void handle_um_drb_pdu(srslte::unique_byte_buffer_t pdu);
void handle_am_drb_pdu(srslte::unique_byte_buffer_t pdu);
};
/****************************************************************************
@ -91,7 +91,7 @@ private:
***************************************************************************/
void pdcp_pack_control_pdu(uint32_t sn, byte_buffer_t* sdu);
void pdcp_unpack_control_pdu(byte_buffer_t* sdu, uint32_t* sn, uint8_t* mac);
void pdcp_unpack_control_pdu_sn(byte_buffer_t* sdu, uint32_t* sn);
void pdcp_pack_data_pdu_short_sn(uint32_t sn, byte_buffer_t* sdu);
void pdcp_unpack_data_pdu_short_sn(byte_buffer_t* sdu, uint32_t* sn);

View File

@ -223,4 +223,33 @@ void pdcp_entity_base::cipher_decrypt(uint8_t* ct, uint32_t ct_len, uint32_t cou
}
log->debug_hex(msg, ct_len, "Cipher decrypt output msg");
}
/****************************************************************************
* Common pack functions
***************************************************************************/
void pdcp_entity_base::extract_mac(const unique_byte_buffer_t& pdu, uint8_t* mac)
{
// Check enough space for MAC
if (pdu->N_bytes < 4) {
log->error("PDU too small to extract MAC-I\n");
return;
}
// Extract MAC
memcpy(mac, &pdu->msg[pdu->N_bytes - 4], 4);
pdu->N_bytes -= 4;
}
void pdcp_entity_base::append_mac(const unique_byte_buffer_t& sdu, uint8_t* mac)
{
// Check enough space for MAC
if (sdu->N_bytes + 4 > sdu->get_tailroom()) {
log->error("Not enough space to add MAC-I\n");
return;
}
// Append MAC
memcpy(&sdu->msg[sdu->N_bytes], mac, 4);
sdu->N_bytes += 4;
}
} // namespace srslte

View File

@ -154,16 +154,12 @@ void pdcp_entity_lte::write_pdu(unique_byte_buffer_t pdu)
std::unique_lock<std::mutex> lock(mutex);
if (is_srb()) {
bool integrity_valid = handle_srb_pdu(pdu);
if (integrity_valid) {
rrc->write_pdu(lcid, std::move(pdu));
}
handle_srb_pdu(std::move(pdu));
} else if (is_drb() && rlc->rb_is_um(lcid)) {
handle_um_drb_pdu(pdu);
handle_um_drb_pdu(std::move(pdu));
gw->write_pdu(lcid, std::move(pdu));
} else if (is_drb() && !rlc->rb_is_um(lcid)) {
handle_am_drb_pdu(pdu);
gw->write_pdu(lcid, std::move(pdu));
handle_am_drb_pdu(std::move(pdu));
} else {
log->error("Invalid PDCP/RLC configuration");
}
@ -174,14 +170,12 @@ void pdcp_entity_lte::write_pdu(unique_byte_buffer_t pdu)
* Ref: 3GPP TS 36.323 v10.1.0 Section 5.1.2
***************************************************************************/
// SRBs (5.1.2.2)
// Returns a boolean indicating whether integrity has passed
bool pdcp_entity_lte::handle_srb_pdu(const srslte::unique_byte_buffer_t& pdu)
void pdcp_entity_lte::handle_srb_pdu(srslte::unique_byte_buffer_t pdu)
{
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", rrc->get_rb_name(lcid).c_str());
uint32_t sn;
uint8_t mac[4];
pdcp_unpack_control_pdu(pdu.get(), &sn, mac);
// Read recvd SN from header
uint32_t sn = SN(pdu->msg[0]);
log->debug("RX SRB PDU. Next_PDCP_RX_SN %d, SN %d", next_pdcp_rx_sn, sn);
@ -193,19 +187,27 @@ bool pdcp_entity_lte::handle_srb_pdu(const srslte::unique_byte_buffer_t& pdu)
count = COUNT(rx_hfn, sn);
}
// Perform integrity checks and decription
// Perform decription
if (do_encryption) {
cipher_decrypt(pdu->msg, pdu->N_bytes, count, pdu->msg);
cipher_decrypt(&pdu->msg[1], pdu->N_bytes - 1, count, pdu->msg);
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str());
}
// Extract MAC
uint8_t mac[4];
extract_mac(pdu, mac);
// Perfrom integrity checks
if (do_integrity) {
if (not integrity_verify(pdu->msg, pdu->N_bytes, count, mac)) {
log->error_hex(pdu->msg, pdu->N_bytes, "%s Dropping PDU", rrc->get_rb_name(lcid).c_str());
return false;
return; // Discard
}
}
// Discard header
pdu->msg++;
// Update state variables
if (sn < next_pdcp_rx_sn) {
rx_hfn++;
@ -217,11 +219,14 @@ bool pdcp_entity_lte::handle_srb_pdu(const srslte::unique_byte_buffer_t& pdu)
rx_hfn++;
}
return true;
// Pass to upper layers
log->info_hex(pdu->msg, pdu->N_bytes, "Passing SDU to upper layers");
rrc->write_pdu(lcid, std::move(pdu));
return;
}
// DRBs mapped on RLC UM (5.1.2.1.3)
void pdcp_entity_lte::handle_um_drb_pdu(const srslte::unique_byte_buffer_t& pdu)
void pdcp_entity_lte::handle_um_drb_pdu(srslte::unique_byte_buffer_t pdu)
{
uint32_t sn;
if (12 == cfg.sn_len) {
@ -246,12 +251,14 @@ void pdcp_entity_lte::handle_um_drb_pdu(const srslte::unique_byte_buffer_t& pdu)
rx_hfn++;
}
// Pass to upper layers
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", rrc->get_rb_name(lcid).c_str(), sn);
gw->write_pdu(lcid, std::move(pdu));
return;
}
// DRBs mapped on RLC AM, without re-ordering (5.1.2.1.2)
void pdcp_entity_lte::handle_am_drb_pdu(const srslte::unique_byte_buffer_t& pdu)
void pdcp_entity_lte::handle_am_drb_pdu(srslte::unique_byte_buffer_t pdu)
{
uint32_t sn, count;
pdcp_unpack_data_pdu_long_sn(pdu.get(), &sn);
@ -266,16 +273,16 @@ void pdcp_entity_lte::handle_am_drb_pdu(const srslte::unique_byte_buffer_t& pdu)
last_submitted_pdcp_rx_sn,
next_pdcp_rx_sn);
bool discard = false;
// Handle PDU
if ((0 <= sn_diff_last_submit && sn_diff_last_submit > (int32_t)reordering_window) ||
(0 <= last_submit_diff_sn && last_submit_diff_sn < (int32_t)reordering_window)) {
log->debug("|SN - last_submitted_sn| is larger than re-ordering window.\n");
log->warning("|SN - last_submitted_sn| is larger than re-ordering window.\n");
if (sn > next_pdcp_rx_sn) {
count = (rx_hfn - 1) << cfg.sn_len | sn;
} else {
count = rx_hfn << cfg.sn_len | sn;
}
discard = true;
return; // Discard
} else if ((int32_t)(next_pdcp_rx_sn - sn) > (int32_t)reordering_window) {
log->debug("(Next_PDCP_RX_SN - SN) is larger than re-ordering window.\n");
rx_hfn++;
@ -297,13 +304,16 @@ void pdcp_entity_lte::handle_am_drb_pdu(const srslte::unique_byte_buffer_t& pdu)
count = (rx_hfn << cfg.sn_len) | sn;
}
// TODO Check if PDU is not due to re-establishment of lower layers?
// Decrypt
cipher_decrypt(pdu->msg, pdu->N_bytes, count, pdu->msg);
log->debug_hex(pdu->msg, pdu->N_bytes, "RX %s PDU (decrypted)", rrc->get_rb_name(lcid).c_str());
if (!discard) {
last_submitted_pdcp_rx_sn = sn;
}
// Update info on last PDU submitted to upper layers
last_submitted_pdcp_rx_sn = sn;
// Pass to upper layers
log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU SN: %d", rrc->get_rb_name(lcid).c_str(), sn);
gw->write_pdu(lcid, std::move(pdu));
return;
}
@ -360,17 +370,12 @@ void pdcp_pack_control_pdu(uint32_t sn, byte_buffer_t* sdu)
sdu->msg[sdu->N_bytes++] = PDCP_CONTROL_MAC_I & 0xFF;
}
void pdcp_unpack_control_pdu(byte_buffer_t* sdu, uint32_t* sn, uint8_t *mac)
void pdcp_unpack_control_pdu_sn(byte_buffer_t* sdu, uint32_t* sn)
{
// Strip header
*sn = sdu->msg[0] & 0x1Fu;
sdu->msg++;
sdu->N_bytes--;
memcpy(mac, &sdu->msg[sdu->N_bytes - 4], 4);
printf("MAC-I (copy) 0x%02x%02x%02x%02x\n", sdu->msg[sdu->N_bytes - 4], sdu->msg[sdu->N_bytes - 3], sdu->msg[sdu->N_bytes - 2], sdu->msg[sdu->N_bytes - 1]);
printf("MAC-I (sdu ) 0x%02x%02x%02x%02x\n", mac[0], mac[1], mac[2], mac[3]);
sdu->N_bytes -= 4;
}
void pdcp_pack_data_pdu_short_sn(uint32_t sn, byte_buffer_t* sdu)

View File

@ -285,31 +285,6 @@ void pdcp_entity_nr::write_data_header(const srslte::unique_byte_buffer_t& sdu,
}
}
void pdcp_entity_nr::extract_mac(const unique_byte_buffer_t& pdu, uint8_t* mac)
{
// Check enough space for MAC
if (pdu->N_bytes < 4) {
log->error("PDU too small to extract MAC-I\n");
return;
}
// Extract MAC
memcpy(mac, &pdu->msg[pdu->N_bytes - 4], 4);
pdu->N_bytes -= 4;
}
void pdcp_entity_nr::append_mac(const unique_byte_buffer_t& sdu, uint8_t* mac)
{
// Check enough space for MAC
if (sdu->N_bytes + 4 > sdu->get_tailroom()) {
log->error("Not enough space to add MAC-I\n");
return;
}
// Append MAC
memcpy(&sdu->msg[sdu->N_bytes], mac, 4);
sdu->N_bytes += 4;
}
// Deliver all consecutivly associated COUNTs.
// Update RX_NEXT after submitting to higher layers