diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index 2c853d8eb61c3830109bd7db9b96f0dc6804403c..182f4c385f093044a852543482a1e4170d881c4d 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -111,13 +111,12 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1); if (entity->has_integrity) { - unsigned char integrity[4]; + unsigned char integrity[4] = {0}; entity->integrity(entity->integrity_context, integrity, buffer, size - integrity_size, entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1); if (memcmp(integrity, buffer + size - integrity_size, 4) != 0) { LOG_E(PDCP, "discard NR PDU, integrity failed\n"); -// return; entity->stats.rxpdu_dd_pkts++; entity->stats.rxpdu_dd_bytes += size; @@ -220,20 +219,27 @@ static void nr_pdcp_entity_recv_sdu(nr_pdcp_entity_t *entity, memcpy(buf + header_size, buffer, size); - if (entity->has_integrity) + if (entity->has_integrity){ + uint8_t integrity[4] = {0}; entity->integrity(entity->integrity_context, - (unsigned char *)buf + header_size + size, + integrity, (unsigned char *)buf, header_size + size, entity->rb_id, count, entity->is_gnb ? 1 : 0); + memcpy((unsigned char *)buf + header_size + size, integrity, 4); + } + // set MAC-I to 0 for SRBs with integrity not active else if (integrity_size == 4) memset(buf + header_size + size, 0, 4); - if (entity->has_ciphering) + if (entity->has_ciphering && (entity->is_gnb || entity->security_mode_completed)){ entity->cipher(entity->security_context, (unsigned char *)buf + header_size, size + integrity_size, entity->rb_id, count, entity->is_gnb ? 1 : 0); + } else { + entity->security_mode_completed = true; + } entity->tx_next++; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 19445887f43f385d8fdddf9cb18e7f099a1428d6..302ea8f0be90432fc526d8dc132f56c3d33bca8d 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -22,6 +22,7 @@ #ifndef _NR_PDCP_ENTITY_H_ #define _NR_PDCP_ENTITY_H_ +#include #include #include "nr_pdcp_sdu.h" @@ -149,6 +150,19 @@ typedef struct nr_pdcp_entity_t { int rx_size; int rx_maxsize; nr_pdcp_statistics_t stats; + + // WARNING: This is a hack! + // 3GPP TS 38.331 (RRC) version 15.3 + // Section 5.3.4.3 Reception of the SecurityModeCommand by the UE + // The UE needs to send the Security Mode Complete message. However, the message + // needs to be sent without being ciphered. + // However: + // 1- The Security Mode Command arrives to the UE with the cipher algo (e.g., nea2). + // 2- The UE is configured with the cipher algo. + // 3- The Security Mode Complete message is sent to the itti task queue. + // 4- The ITTI task, forwards the message ciphering (e.g., nea2) it. + // 5- The gNB cannot understand the ciphered Security Mode Complete message. + bool security_mode_completed; } nr_pdcp_entity_t; nr_pdcp_entity_t *new_nr_pdcp_entity( diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index ece0b0274d20562a590c629f48387ca70f309ddf..81b5e5e8acb8d313255d9e2a23d68a4a263417a8 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -1267,6 +1267,7 @@ void pdcp_config_set_security( ciphering_algorithm = security_modeP & 0x0f; rb->set_security(rb, integrity_algorithm, (char *)kRRCint_pP, ciphering_algorithm, (char *)kRRCenc_pP); + rb->security_mode_completed = false; } else { LOG_E(PDCP, "%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); exit(1); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c index 52afe95673853799743e5511ea39c8fb112deb66..a7479a50329879793ab2f94443f7eda13f88190f 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c @@ -54,14 +54,13 @@ void nr_pdcp_security_nea2_cipher(void *security_context, unsigned char *buffer, int length, int bearer, int count, int direction) { - unsigned char t[16]; + unsigned char t[16] = {0}; t[0] = (count >> 24) & 255; t[1] = (count >> 16) & 255; t[2] = (count >> 8) & 255; t[3] = (count ) & 255; t[4] = ((bearer-1) << 3) | (direction << 2); - memset(&t[5], 0, 16-5); nettle_ctr_crypt(security_context, nettle_aes128.encrypt, nettle_aes128.block_size, t,