From 7cceaa3fae61e0d66e7bcf5c83615bd352e3f97b Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 8 Feb 2024 15:28:09 +0100 Subject: [PATCH 01/11] nrUE: report nea2 support in the capabilities --- openair3/NAS/NR_UE/nr_nas_msg_sim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair3/NAS/NR_UE/nr_nas_msg_sim.c b/openair3/NAS/NR_UE/nr_nas_msg_sim.c index cf1897ae16..57c3e1df58 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg_sim.c +++ b/openair3/NAS/NR_UE/nr_nas_msg_sim.c @@ -466,7 +466,7 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) mm_msg->registration_request.presencemask |= REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT; mm_msg->registration_request.nruesecuritycapability.iei = REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_IEI; mm_msg->registration_request.nruesecuritycapability.length = 8; - mm_msg->registration_request.nruesecuritycapability.fg_EA = 0x80; + mm_msg->registration_request.nruesecuritycapability.fg_EA = 0xa0; mm_msg->registration_request.nruesecuritycapability.fg_IA = 0x20; mm_msg->registration_request.nruesecuritycapability.EEA = 0; mm_msg->registration_request.nruesecuritycapability.EIA = 0; From f85e3adc5ad033c3fc5e5057626134c9520d5049 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 9 Feb 2024 09:41:25 +0100 Subject: [PATCH 02/11] nrUE: bugfix/improvement in security mode handling The use of security_mode_completed in the PDCP entity was a hack. Plus it was not working at all with the deregistration request when nea2 is used, sent when doing ctrl+c in the nrUE. So let's remove it. And let's handle activation of integrity and ciphering more in accordance with what 38.331 says. SecurityModeComplete has to be sent integrity protected, but not ciphered. Only after should the ciphering be activated. (See 38.331 5.3.4.3.) --- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c | 4 +--- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h | 13 ------------- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 1 - openair2/RRC/NR_UE/rrc_UE.c | 14 +++++++++++++- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index 2a197c3c4f..374d1cfd55 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -261,13 +261,11 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity, memset(buf + header_size + size, 0, PDCP_INTEGRITY_SIZE); } - if (entity->has_ciphering && (entity->is_gnb || entity->security_mode_completed)) { + if (entity->has_ciphering) { entity->cipher(entity->security_context, (unsigned char *)buf + header_size + sdap_header_size, size + integrity_size - sdap_header_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 aae1ffb317..82f701f037 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -167,19 +167,6 @@ typedef struct nr_pdcp_entity_t { 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; - /* Keep tracks of whether the PDCP entity was suspended or not */ bool entity_suspended; } nr_pdcp_entity_t; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index b2380e3b2f..8d3ce255e3 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -1056,7 +1056,6 @@ void nr_pdcp_config_set_security(ue_id_t ue_id, ciphering_algorithm = security_modeP & 0x0f; rb->set_security(rb, integrity_algorithm, (char *)kRRCint_pP, ciphering_algorithm, (char *)kRRCenc_pP); - rb->security_mode_completed = false; nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 42540222f0..d508bdaa09 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1073,7 +1073,8 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, log_dump(NR_RRC, ue_rrc->kgnb, 32, LOG_DUMP_CHAR, "driving kRRCenc, kRRCint and kUPenc from KgNB="); if (securityMode != 0xff) { - uint8_t security_mode = ue_rrc->cipheringAlgorithm | (ue_rrc->integrityProtAlgorithm << 4); + /* for SecurityModeComplete, ciphering is not activated yet, only integrity */ + uint8_t security_mode = ue_rrc->integrityProtAlgorithm << 4; // configure lower layers to apply SRB integrity protection and ciphering for (int i = 1; i < NR_NUM_SRB; i++) { if (ue_rrc->Srb[i] == RB_ESTABLISHED) @@ -1119,6 +1120,17 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, "securityModeCommand->criticalExtensions.present (%d) != " "NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand\n", securityModeCommand->criticalExtensions.present); + + if (securityMode != 0xff) { + /* after encoding SecurityModeComplete we activate both ciphering and integrity */ + uint8_t security_mode = ue_rrc->cipheringAlgorithm | (ue_rrc->integrityProtAlgorithm << 4); + // configure lower layers to apply SRB integrity protection and ciphering + for (int i = 1; i < NR_NUM_SRB; i++) { + if (ue_rrc->Srb[i] == RB_ESTABLISHED) + /* pass NULL to keep current keys */ + nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, NULL, NULL, NULL); + } + } } static void handle_meas_reporting_remove(rrcPerNB_t *rrc, int id, NR_UE_Timers_Constants_t *timers) From d4d534f1ef531392fe43c571bfdb012a5abd3714 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 9 Feb 2024 10:05:30 +0100 Subject: [PATCH 03/11] nrUE: bugfix: derive and use correct security keys for DRBs --- openair2/RRC/NR_UE/rrc_UE.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index d508bdaa09..f428d4f6a6 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1403,6 +1403,9 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; uint8_t kRRCint[NR_K_KEY_SIZE] = {0}; + uint8_t kUPenc[NR_K_KEY_SIZE] = {0}; + uint8_t kUPint[NR_K_KEY_SIZE] = {0}; + if (ue_rrc->as_security_activated) { if (radioBearerConfig->securityConfig != NULL) { // When the field is not included, continue to use the currently configured keyToUse @@ -1419,6 +1422,8 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, } nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kRRCenc); nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, kRRCint); + nr_derive_key(UP_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kUPenc); + nr_derive_key(UP_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, kUPint); } if (radioBearerConfig->srb_ToAddModList != NULL) { @@ -1489,8 +1494,8 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, radioBearerConfig->drb_ToAddModList->list.array[cnt], ue_rrc->cipheringAlgorithm, ue_rrc->integrityProtAlgorithm, - kRRCenc, - kRRCint); + kUPenc, + kUPint); } } } // drb_ToAddModList // From cc61d4f7beca5c6668e33fb530c13eaeb03a75e4 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 9 Feb 2024 11:16:15 +0100 Subject: [PATCH 04/11] nr pdcp: pass MAC-I and header to upper layers Needed by some RRC procedures to validate the integrity of a message before accepting it. --- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c | 35 +++++++++++++++++++---- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h | 6 ++-- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 6 ++-- openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c | 5 +++- openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h | 12 +++++++- 5 files changed, 52 insertions(+), 12 deletions(-) diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index 374d1cfd55..a90be5f7f0 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -55,6 +55,8 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, int sdap_header_size = 0; int rx_deliv_sn; uint32_t rx_deliv_hfn; + uint32_t mac = 0; + uint32_t header = 0; if (entity->entity_suspended) { LOG_W(PDCP, "PDCP entity %d is suspended. Quit RX procedure.\n", entity->rb_id); @@ -121,6 +123,21 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, rcvd_count = (rcvd_hfn << entity->sn_size) | rcvd_sn; + /* the MAC-I/header/rcvd_count is needed by some RRC procedures, store it */ + if (entity->has_integrity || entity->type == NR_PDCP_SRB) { + mac = (uint32_t)buffer[size-4] + | ((uint32_t)buffer[size-3] << 8) + | ((uint32_t)buffer[size-2] << 16) + | ((uint32_t)buffer[size-1] << 24); + + /* higher byte of 'header' is its size, next 2 or 3 bytes are the header */ + header = (uint32_t)header_size << 24; + if (header_size == 2) + header |= (buffer[0] << 16) | (buffer[1] << 8); + else + header |= (buffer[0] << 16) | (buffer[1] << 8) | buffer[2]; + } + if (entity->has_ciphering) entity->cipher(entity->security_context, buffer + header_size + sdap_header_size, @@ -152,7 +169,8 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, sdu = nr_pdcp_new_sdu(rcvd_count, (char *)buffer + header_size, - size - header_size - integrity_size); + size - header_size - integrity_size, + mac, header); entity->rx_list = nr_pdcp_sdu_list_add(entity->rx_list, sdu); entity->rx_size += size-header_size; @@ -168,7 +186,8 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, while (entity->rx_list != NULL && count == entity->rx_list->count) { nr_pdcp_sdu_t *cur = entity->rx_list; entity->deliver_sdu(entity->deliver_sdu_data, entity, - cur->buffer, cur->size); + cur->buffer, cur->size, + cur->mac, cur->header, cur->count); entity->rx_list = cur->next; entity->rx_size -= cur->size; entity->stats.txsdu_pkts++; @@ -358,7 +377,8 @@ static void check_t_reordering(nr_pdcp_entity_t *entity) while (entity->rx_list != NULL && entity->rx_list->count < entity->rx_reord) { nr_pdcp_sdu_t *cur = entity->rx_list; entity->deliver_sdu(entity->deliver_sdu_data, entity, - cur->buffer, cur->size); + cur->buffer, cur->size, + cur->mac, cur->header, cur->count); entity->rx_list = cur->next; entity->rx_size -= cur->size; entity->stats.txsdu_pkts++; @@ -371,7 +391,8 @@ static void check_t_reordering(nr_pdcp_entity_t *entity) while (entity->rx_list != NULL && count == entity->rx_list->count) { nr_pdcp_sdu_t *cur = entity->rx_list; entity->deliver_sdu(entity->deliver_sdu_data, entity, - cur->buffer, cur->size); + cur->buffer, cur->size, + cur->mac, cur->header, cur->count); entity->rx_list = cur->next; entity->rx_size -= cur->size; entity->stats.txsdu_pkts++; @@ -401,7 +422,8 @@ static void deliver_all_sdus(nr_pdcp_entity_t *entity) while (entity->rx_list != NULL) { nr_pdcp_sdu_t *cur = entity->rx_list; entity->deliver_sdu(entity->deliver_sdu_data, entity, - cur->buffer, cur->size); + cur->buffer, cur->size, + cur->mac, cur->header, cur->count); entity->rx_list = cur->next; entity->rx_size -= cur->size; entity->stats.txsdu_pkts++; @@ -522,7 +544,8 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( bool has_sdap_rx, bool has_sdap_tx, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, - char *buf, int size), + char *buf, int size, + uint32_t mac, uint32_t header, uint32_t count), void *deliver_sdu_data, void (*deliver_pdu)(void *deliver_pdu_data, ue_id_t ue_id, int rb_id, char *buf, int size, int sdu_id), diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 82f701f037..94689eac76 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -108,7 +108,8 @@ typedef struct nr_pdcp_entity_t { /* callbacks provided to the PDCP module */ void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, - char *buf, int size); + char *buf, int size, + uint32_t mac, uint32_t header, uint32_t count); void *deliver_sdu_data; void (*deliver_pdu)(void *deliver_pdu_data, ue_id_t ue_id, int rb_id, char *buf, int size, int sdu_id); @@ -179,7 +180,8 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( bool has_sdap_rx, bool has_sdap_tx, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, - char *buf, int size), + char *buf, int size, + uint32_t mac, uint32_t header, uint32_t count), void *deliver_sdu_data, void (*deliver_pdu)(void *deliver_pdu_data, ue_id_t ue_id, int rb_id, char *buf, int size, int sdu_id), diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index 8d3ce255e3..e1d659b3d4 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -658,7 +658,8 @@ uint64_t nr_pdcp_module_init(uint64_t _pdcp_optmask, int id) } static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity, - char *buf, int size) + char *buf, int size, + uint32_t mac, uint32_t header, uint32_t count) { nr_pdcp_ue_t *ue = _ue; int rb_id; @@ -741,7 +742,8 @@ static void deliver_pdu_drb_gnb(void *deliver_pdu_data, ue_id_t ue_id, int rb_id } static void deliver_sdu_srb(void *_ue, nr_pdcp_entity_t *entity, - char *buf, int size) + char *buf, int size, + uint32_t mac, uint32_t header, uint32_t count) { nr_pdcp_ue_t *ue = _ue; int srb_id; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c index 47d95156e3..48af4b945a 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c @@ -24,7 +24,8 @@ #include #include -nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size) +nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size, + uint32_t mac, uint32_t header) { nr_pdcp_sdu_t *ret = calloc(1, sizeof(nr_pdcp_sdu_t)); if (ret == NULL) @@ -35,6 +36,8 @@ nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size) exit(1); memcpy(ret->buffer, buffer, size); ret->size = size; + ret->mac = mac; + ret->header = header; return ret; } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h index 3d4e50a4ce..91d63fefe1 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h @@ -28,10 +28,20 @@ typedef struct nr_pdcp_sdu_t { uint32_t count; char *buffer; int size; + uint32_t mac; + /* 'header' is decomposed into two parts: higher byte is the size of the + * header (2 or 3 bytes), then the next two or three bytes are the header + * so the size is: (header >> 24) & 0xff + * and first byte of header is: (header >> 16) & 0xff + * second byte of header is: (header >> 8) & 0xff + * and if there is a third, it is: header & 0xff + */ + uint32_t header; struct nr_pdcp_sdu_t *next; } nr_pdcp_sdu_t; -nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size); +nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size, + uint32_t mac, uint32_t header); nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu); int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count); void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu); From b9f0299165142173010df94fbaf176ff3bf1e7ab Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 9 Feb 2024 12:07:28 +0100 Subject: [PATCH 05/11] nrUE: simplify nr_rrc_ue_process_securityModeCommand() The case securityModeFailure didn't seem to be implemented properly, so I just removed it entirely. The variable 'securityMode' did not make much sense, removed as well. Plus for integrity, there was: securityMode |= 1 << 5 for nea1 and << 6 for nea2, which does not seem correct (I would expect << 4 and << 5 respectively), so it was properly incorrect. 'securityModeCommand->criticalExtensions.choice.securityModeCommand' was accessed before checking that 'securityModeCommand->criticalExtensions.present' is 'NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand', which is wrong. The tests 'securityMode >= NO_SECURITY_MODE' and 'securityMode != 0xff' don't make sense/are unclear, so removed too. So let's simplify this function, wrong in several places. And put some AssertFatal() so that the code won't do weird things. The AssertFatal() can be removed later and the function improved later if needed. The case securityModeFailure can also be handled later, but I think there is more work to do than just encoding the message and send it to the gNB, so it's not bad to remove it for the moment. --- openair2/RRC/NR_UE/rrc_UE.c | 136 +++++++++++++++--------------------- 1 file changed, 56 insertions(+), 80 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index f428d4f6a6..076728e925 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1006,9 +1006,15 @@ static int8_t nr_rrc_ue_decode_ccch(NR_UE_RRC_INST_t *rrc, static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, NR_SecurityModeCommand_t *const securityModeCommand) { - int securityMode = 0; + uint8_t security_mode; + LOG_I(NR_RRC, "Receiving from SRB1 (DL-DCCH), Processing securityModeCommand\n"); + AssertFatal(securityModeCommand->criticalExtensions.present == NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand, + "securityModeCommand->criticalExtensions.present (%d) != " + "NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand\n", + securityModeCommand->criticalExtensions.present); + NR_SecurityConfigSMC_t *securityConfigSMC = &securityModeCommand->criticalExtensions.choice.securityModeCommand->securityConfigSMC; @@ -1016,52 +1022,34 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, case NR_CipheringAlgorithm_nea0: case NR_CipheringAlgorithm_nea1: case NR_CipheringAlgorithm_nea2: - LOG_I(NR_RRC, "Security algorithm is set to nea%d\n", securityMode); - securityMode = securityConfigSMC->securityAlgorithmConfig.cipheringAlgorithm; + LOG_I(NR_RRC, "Security algorithm is set to nea%ld\n", + securityConfigSMC->securityAlgorithmConfig.cipheringAlgorithm); break; default: - LOG_W(NR_RRC, "Security algorithm is set to none\n"); - securityMode = NR_CipheringAlgorithm_spare1; - break; + AssertFatal(0, "Security algorithm not known/supported\n"); } ue_rrc->cipheringAlgorithm = securityConfigSMC->securityAlgorithmConfig.cipheringAlgorithm; + ue_rrc->integrityProtAlgorithm = 0; if (securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm != NULL) { switch (*securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm) { + case NR_IntegrityProtAlgorithm_nia0: case NR_IntegrityProtAlgorithm_nia1: - LOG_I(NR_RRC, "Integrity protection algorithm is set to nia1\n"); - securityMode |= 1 << 5; - break; - case NR_IntegrityProtAlgorithm_nia2: - LOG_I(NR_RRC, "Integrity protection algorithm is set to nia2\n"); - securityMode |= 1 << 6; + LOG_I(NR_RRC, "Integrity protection algorithm is set to nia%ld\n", *securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm); break; - default: - LOG_I(NR_RRC, "Integrity protection algorithm is set to none\n"); - securityMode |= 0x70; - break; + AssertFatal(0, "Integrity algorithm not known/supported\n"); } - ue_rrc->integrityProtAlgorithm = *securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm; } - LOG_D(NR_RRC, "security mode is %x \n", securityMode); NR_UL_DCCH_Message_t ul_dcch_msg = {0}; - // memset((void *)&SecurityModeCommand,0,sizeof(SecurityModeCommand_t)); ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; asn1cCalloc(ul_dcch_msg.message.choice.c1, c1); - if (securityMode >= NO_SECURITY_MODE) { - LOG_I(NR_RRC, "rrc_ue_process_securityModeCommand, security mode complete case \n"); - c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete; - } else { - LOG_I(NR_RRC, "rrc_ue_process_securityModeCommand, security mode failure case \n"); - c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeFailure; - c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete; - } + c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete; uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; uint8_t kUPenc[NR_K_KEY_SIZE] = {0}; @@ -1070,66 +1058,54 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kRRCenc); nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, kRRCint); - log_dump(NR_RRC, ue_rrc->kgnb, 32, LOG_DUMP_CHAR, "driving kRRCenc, kRRCint and kUPenc from KgNB="); + log_dump(NR_RRC, ue_rrc->kgnb, 32, LOG_DUMP_CHAR, "deriving kRRCenc, kRRCint and kUPenc from KgNB="); - if (securityMode != 0xff) { - /* for SecurityModeComplete, ciphering is not activated yet, only integrity */ - uint8_t security_mode = ue_rrc->integrityProtAlgorithm << 4; - // configure lower layers to apply SRB integrity protection and ciphering - for (int i = 1; i < NR_NUM_SRB; i++) { - if (ue_rrc->Srb[i] == RB_ESTABLISHED) - nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, kRRCenc, kRRCint, kUPenc); - } - } else { - LOG_I(NR_RRC, "skipped pdcp_config_set_security() as securityMode == 0x%02x", securityMode); + /* for SecurityModeComplete, ciphering is not activated yet, only integrity */ + security_mode = ue_rrc->integrityProtAlgorithm << 4; + // configure lower layers to apply SRB integrity protection and ciphering + for (int i = 1; i < NR_NUM_SRB; i++) { + if (ue_rrc->Srb[i] == RB_ESTABLISHED) + nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, kRRCenc, kRRCint, kUPenc); } - if (securityModeCommand->criticalExtensions.present == NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand) { - asn1cCalloc(c1->choice.securityModeComplete, modeComplete); - modeComplete->rrc_TransactionIdentifier = securityModeCommand->rrc_TransactionIdentifier; - modeComplete->criticalExtensions.present = NR_SecurityModeComplete__criticalExtensions_PR_securityModeComplete; - asn1cCalloc(modeComplete->criticalExtensions.choice.securityModeComplete, ext); - ext->nonCriticalExtension = NULL; - LOG_I(NR_RRC, - "Receiving from SRB1 (DL-DCCH), encoding securityModeComplete, rrc_TransactionIdentifier: %ld\n", - securityModeCommand->rrc_TransactionIdentifier); - uint8_t buffer[200]; - asn_enc_rval_t enc_rval = - uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, sizeof(buffer)); - AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded); + asn1cCalloc(c1->choice.securityModeComplete, modeComplete); + modeComplete->rrc_TransactionIdentifier = securityModeCommand->rrc_TransactionIdentifier; + modeComplete->criticalExtensions.present = NR_SecurityModeComplete__criticalExtensions_PR_securityModeComplete; + asn1cCalloc(modeComplete->criticalExtensions.choice.securityModeComplete, ext); + ext->nonCriticalExtension = NULL; + LOG_I(NR_RRC, + "Receiving from SRB1 (DL-DCCH), encoding securityModeComplete, rrc_TransactionIdentifier: %ld\n", + securityModeCommand->rrc_TransactionIdentifier); + uint8_t buffer[200]; + asn_enc_rval_t enc_rval = + uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, sizeof(buffer)); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded); - if (LOG_DEBUGFLAG(DEBUG_ASN1)) { - xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); - } - log_dump(NR_RRC, buffer, 16, LOG_DUMP_CHAR, "securityModeComplete payload: "); - LOG_D(NR_RRC, "securityModeComplete Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded + 7) / 8); - ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_UL_DCCH_Message, &ul_dcch_msg); + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); + } + log_dump(NR_RRC, buffer, 16, LOG_DUMP_CHAR, "securityModeComplete payload: "); + LOG_D(NR_RRC, "securityModeComplete Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded + 7) / 8); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_UL_DCCH_Message, &ul_dcch_msg); - for (int i = 0; i < (enc_rval.encoded + 7) / 8; i++) { - LOG_T(NR_RRC, "%02x.", buffer[i]); - } - LOG_T(NR_RRC, "\n"); + for (int i = 0; i < (enc_rval.encoded + 7) / 8; i++) { + LOG_T(NR_RRC, "%02x.", buffer[i]); + } + LOG_T(NR_RRC, "\n"); - // TODO the SecurityModeCommand message needs to pass the integrity protection check - // for the UE to declare AS security to be activated - ue_rrc->as_security_activated = true; - int srb_id = 1; // SecurityModeComplete in SRB1 - nr_pdcp_data_req_srb(ue_rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL); - } else - LOG_W(NR_RRC, - "securityModeCommand->criticalExtensions.present (%d) != " - "NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand\n", - securityModeCommand->criticalExtensions.present); + // TODO the SecurityModeCommand message needs to pass the integrity protection check + // for the UE to declare AS security to be activated + ue_rrc->as_security_activated = true; + int srb_id = 1; // SecurityModeComplete in SRB1 + nr_pdcp_data_req_srb(ue_rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL); - if (securityMode != 0xff) { - /* after encoding SecurityModeComplete we activate both ciphering and integrity */ - uint8_t security_mode = ue_rrc->cipheringAlgorithm | (ue_rrc->integrityProtAlgorithm << 4); - // configure lower layers to apply SRB integrity protection and ciphering - for (int i = 1; i < NR_NUM_SRB; i++) { - if (ue_rrc->Srb[i] == RB_ESTABLISHED) - /* pass NULL to keep current keys */ - nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, NULL, NULL, NULL); - } + /* after encoding SecurityModeComplete we activate both ciphering and integrity */ + security_mode = ue_rrc->cipheringAlgorithm | (ue_rrc->integrityProtAlgorithm << 4); + // configure lower layers to apply SRB integrity protection and ciphering + for (int i = 1; i < NR_NUM_SRB; i++) { + if (ue_rrc->Srb[i] == RB_ESTABLISHED) + /* pass NULL to keep current keys */ + nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, NULL, NULL, NULL); } } From 4e625b01d21441082f6140532b107838a7f8d8b7 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 9 Feb 2024 14:34:10 +0100 Subject: [PATCH 06/11] nr pdcp: add an API function to check integrity --- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c | 41 ++++++++++++++++++++--- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h | 7 ++++ openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 30 +++++++++++++++++ openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h | 8 +++++ 4 files changed, 82 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index a90be5f7f0..7e38c4fa9d 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -296,6 +296,38 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity, return header_size + size + integrity_size; } +static bool nr_pdcp_entity_check_integrity(struct nr_pdcp_entity_t *entity, + const uint8_t *buffer, + int buffer_size, + uint32_t mac, + uint32_t header, + uint32_t count) +{ + if (!entity->has_integrity) + return false; + + int header_size = (header >> 24) & 0xff; + + uint8_t b[buffer_size + header_size]; + + b[0] = (header >> 16) & 0xff; + b[1] = (header >> 8) & 0xff; + if (header_size == 3) + b[2] = header & 0xff; + memcpy(b + header_size, buffer, buffer_size); + + unsigned char integrity[4]; + entity->integrity(entity->integrity_context, integrity, + b, buffer_size + header_size, + entity->rb_id, count, entity->is_gnb ? 0 : 1); + uint32_t nmac = (uint32_t)integrity[0] + | ((uint32_t)integrity[1] << 8) + | ((uint32_t)integrity[2] << 16) + | ((uint32_t)integrity[3] << 24); + + return nmac == mac; +} + /* may be called several times, take care to clean previous settings */ static void nr_pdcp_entity_set_security(nr_pdcp_entity_t *entity, int integrity_algorithm, @@ -568,10 +600,11 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( ret->type = type; - ret->recv_pdu = nr_pdcp_entity_recv_pdu; - ret->process_sdu = nr_pdcp_entity_process_sdu; - ret->set_security = nr_pdcp_entity_set_security; - ret->set_time = nr_pdcp_entity_set_time; + ret->recv_pdu = nr_pdcp_entity_recv_pdu; + ret->process_sdu = nr_pdcp_entity_process_sdu; + ret->set_security = nr_pdcp_entity_set_security; + ret->check_integrity = nr_pdcp_entity_check_integrity; + ret->set_time = nr_pdcp_entity_set_time; ret->delete_entity = nr_pdcp_entity_delete; ret->release_entity = nr_pdcp_entity_release; diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 94689eac76..058aabc87e 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -104,6 +104,13 @@ typedef struct nr_pdcp_entity_t { int ciphering_algorithm, char *ciphering_key); + /* check_integrity is used by RRC */ + bool (*check_integrity)(struct nr_pdcp_entity_t *entity, + const uint8_t *buffer, int buffer_length, + uint32_t mac, + uint32_t header, + uint32_t count); + void (*set_time)(struct nr_pdcp_entity_t *entity, uint64_t now); /* callbacks provided to the PDCP module */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index e1d659b3d4..259579d347 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -1062,6 +1062,36 @@ void nr_pdcp_config_set_security(ue_id_t ue_id, nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } +bool nr_pdcp_check_integrity_srb(ue_id_t ue_id, + int srb_id, + const uint8_t *msg, + int msg_size, + uint32_t mac, + uint32_t header, + uint32_t count) +{ + nr_pdcp_ue_t *ue; + nr_pdcp_entity_t *rb; + + nr_pdcp_manager_lock(nr_pdcp_ue_manager); + + ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); + + rb = nr_pdcp_get_rb(ue, srb_id, true); + + if (rb == NULL) { + LOG_E(PDCP, "no SRB found (ue_id %ld, rb_id %d)\n", ue_id, srb_id); + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + return false; + } + + bool ret = rb->check_integrity(rb, msg, msg_size, mac, header, count); + + nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + + return ret; +} + bool nr_pdcp_data_req_srb(ue_id_t ue_id, const rb_id_t rb_id, const mui_t muiP, diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h index be1604dabd..2e87aa9023 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -87,6 +87,14 @@ void nr_pdcp_config_set_security(ue_id_t ue_id, uint8_t *const kRRCint_pP, uint8_t *const kUPenc_pP); +bool nr_pdcp_check_integrity_srb(ue_id_t ue_id, + int srb_id, + const uint8_t *msg, + int msg_size, + uint32_t mac, + uint32_t header, + uint32_t count); + bool cu_f1u_data_req(protocol_ctxt_t *ctxt_pP, const srb_flag_t srb_flagP, const rb_id_t rb_id, From d1f490243e0c73b1886a72cfd64697f7a8eb9882 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 9 Feb 2024 14:39:06 +0100 Subject: [PATCH 07/11] nrUE: check integrity of SecurityModeCommand We AssertFatal() if integrity fails. To be refined if needed. --- openair2/COMMON/pdcp_messages_types.h | 4 +++ openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 3 +++ openair2/RRC/NR_UE/rrc_UE.c | 30 +++++++++++++++++------ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/openair2/COMMON/pdcp_messages_types.h b/openair2/COMMON/pdcp_messages_types.h index d7c84a24a1..0620858223 100644 --- a/openair2/COMMON/pdcp_messages_types.h +++ b/openair2/COMMON/pdcp_messages_types.h @@ -96,6 +96,10 @@ typedef struct NRRrcDcchDataInd_s { uint16_t rnti; uint8_t module_id; uint8_t gNB_index; // LG: needed in UE + /* these three variables are needed for RRC to check integrity of the PDCP SDU */ + uint32_t mac; + uint32_t header; + uint32_t count; } NRRrcDcchDataInd; typedef struct RrcPcchDataReq_s { diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index 259579d347..f0480f7be1 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -784,6 +784,9 @@ srb_found: NR_RRC_DCCH_DATA_IND(message_p).dcch_index = srb_id; NR_RRC_DCCH_DATA_IND(message_p).sdu_p = rrc_buffer_p; NR_RRC_DCCH_DATA_IND(message_p).sdu_size = size; + NR_RRC_DCCH_DATA_IND(message_p).mac = mac; + NR_RRC_DCCH_DATA_IND(message_p).header = header; + NR_RRC_DCCH_DATA_IND(message_p).count = count; ue_id_t ue_id = ue->ue_id; itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, message_p); } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 076728e925..f3230f27e4 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1004,7 +1004,13 @@ static int8_t nr_rrc_ue_decode_ccch(NR_UE_RRC_INST_t *rrc, } static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, - NR_SecurityModeCommand_t *const securityModeCommand) + NR_SecurityModeCommand_t *const securityModeCommand, + int srb_id, + const uint8_t *msg, + int msg_size, + uint32_t mac, + uint32_t header, + uint32_t count) { uint8_t security_mode; @@ -1093,10 +1099,13 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, } LOG_T(NR_RRC, "\n"); - // TODO the SecurityModeCommand message needs to pass the integrity protection check - // for the UE to declare AS security to be activated + // the SecurityModeCommand message needs to pass the integrity protection check + // for the UE to declare AS security to be activated + bool integrity_pass = nr_pdcp_check_integrity_srb(ue_rrc->ue_id, srb_id, msg, msg_size, mac, header, count); + AssertFatal(integrity_pass, "SecurityModeCommand integrity failed\n"); + ue_rrc->as_security_activated = true; - int srb_id = 1; // SecurityModeComplete in SRB1 + srb_id = 1; // SecurityModeComplete in SRB1 nr_pdcp_data_req_srb(ue_rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL); /* after encoding SecurityModeComplete we activate both ciphering and integrity */ @@ -1548,7 +1557,10 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, const srb_id_t Srb_id, const uint8_t *const Buffer, size_t Buffer_size, - const uint8_t gNB_indexP) + const uint8_t gNB_indexP, + uint32_t mac, + uint32_t header, + uint32_t count) { NR_DL_DCCH_Message_t *dl_dcch_msg = NULL; @@ -1632,7 +1644,8 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, break; case NR_DL_DCCH_MessageType__c1_PR_securityModeCommand: LOG_I(NR_RRC, "Received securityModeCommand (gNB %d)\n", gNB_indexP); - nr_rrc_ue_process_securityModeCommand(rrc, c1->choice.securityModeCommand); + nr_rrc_ue_process_securityModeCommand(rrc, c1->choice.securityModeCommand, + Srb_id, Buffer, Buffer_size, mac, header, count); break; } } break; @@ -1737,7 +1750,10 @@ void *rrc_nrue(void *notUsed) NR_RRC_DCCH_DATA_IND(msg_p).dcch_index, NR_RRC_DCCH_DATA_IND(msg_p).sdu_p, NR_RRC_DCCH_DATA_IND(msg_p).sdu_size, - NR_RRC_DCCH_DATA_IND(msg_p).gNB_index); + NR_RRC_DCCH_DATA_IND(msg_p).gNB_index, + NR_RRC_DCCH_DATA_IND(msg_p).mac, + NR_RRC_DCCH_DATA_IND(msg_p).header, + NR_RRC_DCCH_DATA_IND(msg_p).count); break; case NAS_KENB_REFRESH_REQ: From f81a463f995a532f7149f1e1356643ec7697aaac Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 1 Mar 2024 14:44:18 +0100 Subject: [PATCH 08/11] nrUE: reply SecurityModeFailure if integrity of SecurityModeCommand fails --- openair2/RRC/NR_UE/rrc_UE.c | 57 +++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index f3230f27e4..33365e0094 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1050,13 +1050,6 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, ue_rrc->integrityProtAlgorithm = *securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm; } - NR_UL_DCCH_Message_t ul_dcch_msg = {0}; - - ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; - asn1cCalloc(ul_dcch_msg.message.choice.c1, c1); - - c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete; - uint8_t kRRCenc[NR_K_KEY_SIZE] = {0}; uint8_t kUPenc[NR_K_KEY_SIZE] = {0}; uint8_t kRRCint[NR_K_KEY_SIZE] = {0}; @@ -1074,6 +1067,51 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, kRRCenc, kRRCint, kUPenc); } + NR_UL_DCCH_Message_t ul_dcch_msg = {0}; + + ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1; + asn1cCalloc(ul_dcch_msg.message.choice.c1, c1); + + // the SecurityModeCommand message needs to pass the integrity protection check + // for the UE to declare AS security to be activated + bool integrity_pass = nr_pdcp_check_integrity_srb(ue_rrc->ue_id, srb_id, msg, msg_size, mac, header, count); + if (!integrity_pass) { + /* - continue using the configuration used prior to the reception of the SecurityModeCommand message, i.e. + * neither apply integrity protection nor ciphering. + * - submit the SecurityModeFailure message to lower layers for transmission, upon which the procedure ends. + */ + LOG_E(NR_RRC, "integrity of SecurityModeCommand failed, reply with SecurityModeFailure\n"); + c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeFailure; + asn1cCalloc(c1->choice.securityModeFailure, modeFailure); + modeFailure->rrc_TransactionIdentifier = securityModeCommand->rrc_TransactionIdentifier; + modeFailure->criticalExtensions.present = NR_SecurityModeFailure__criticalExtensions_PR_securityModeFailure; + asn1cCalloc(modeFailure->criticalExtensions.choice.securityModeFailure, ext); + ext->nonCriticalExtension = NULL; + + uint8_t buffer[200]; + asn_enc_rval_t enc_rval = + uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, sizeof(buffer)); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded); + if (LOG_DEBUGFLAG(DEBUG_ASN1)) + xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_UL_DCCH_Message, &ul_dcch_msg); + + /* disable both ciphering and integrity */ + security_mode = 0; + for (int i = 1; i < NR_NUM_SRB; i++) { + if (ue_rrc->Srb[i] == RB_ESTABLISHED) + nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, NULL, NULL, NULL); + } + + srb_id = 1; // SecurityModeFailure in SRB1 + nr_pdcp_data_req_srb(ue_rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL); + + return; + } + + /* integrity passed, send SecurityModeComplete */ + c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete; + asn1cCalloc(c1->choice.securityModeComplete, modeComplete); modeComplete->rrc_TransactionIdentifier = securityModeCommand->rrc_TransactionIdentifier; modeComplete->criticalExtensions.present = NR_SecurityModeComplete__criticalExtensions_PR_securityModeComplete; @@ -1099,11 +1137,6 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, } LOG_T(NR_RRC, "\n"); - // the SecurityModeCommand message needs to pass the integrity protection check - // for the UE to declare AS security to be activated - bool integrity_pass = nr_pdcp_check_integrity_srb(ue_rrc->ue_id, srb_id, msg, msg_size, mac, header, count); - AssertFatal(integrity_pass, "SecurityModeCommand integrity failed\n"); - ue_rrc->as_security_activated = true; srb_id = 1; // SecurityModeComplete in SRB1 nr_pdcp_data_req_srb(ue_rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL); From 0f9b335951a4fffa776d87e330ca273d33b4b9ec Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Tue, 26 Mar 2024 17:33:13 +0100 Subject: [PATCH 09/11] minor: move declaration of variable --- openair2/RRC/NR_UE/rrc_UE.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 33365e0094..20e941f90f 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1012,8 +1012,6 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, uint32_t header, uint32_t count) { - uint8_t security_mode; - LOG_I(NR_RRC, "Receiving from SRB1 (DL-DCCH), Processing securityModeCommand\n"); AssertFatal(securityModeCommand->criticalExtensions.present == NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand, @@ -1060,7 +1058,7 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, log_dump(NR_RRC, ue_rrc->kgnb, 32, LOG_DUMP_CHAR, "deriving kRRCenc, kRRCint and kUPenc from KgNB="); /* for SecurityModeComplete, ciphering is not activated yet, only integrity */ - security_mode = ue_rrc->integrityProtAlgorithm << 4; + uint8_t security_mode = ue_rrc->integrityProtAlgorithm << 4; // configure lower layers to apply SRB integrity protection and ciphering for (int i = 1; i < NR_NUM_SRB; i++) { if (ue_rrc->Srb[i] == RB_ESTABLISHED) From a323195aed800aec4b8d7a74dd8e997b3c4d5f60 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Wed, 27 Mar 2024 17:17:35 +0100 Subject: [PATCH 10/11] nr pdcp: improve readability of integrity checking Introduce the structure nr_pdcp_integrity_data_t and adapt code to use it. Note: in nr_pdcp_sdu_t we keep the 'count' variable (which is also present in nr_pdcp_integrity_data_t). They represent the same value, but 'count' in nr_pdcp_integrity_data_t is to be specifically used for integrity while the other one has other uses, so it's better to keep it. --- openair2/COMMON/pdcp_messages_types.h | 14 ++--- openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c | 56 +++++++------------ openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h | 8 +-- .../LAYER2/nr_pdcp/nr_pdcp_integrity_data.h | 34 +++++++++++ openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 14 ++--- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h | 4 +- openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c | 5 +- openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h | 22 +++----- openair2/RRC/NR_UE/rrc_UE.c | 17 ++---- 9 files changed, 86 insertions(+), 88 deletions(-) create mode 100644 openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_data.h diff --git a/openair2/COMMON/pdcp_messages_types.h b/openair2/COMMON/pdcp_messages_types.h index 0620858223..b97fdef986 100644 --- a/openair2/COMMON/pdcp_messages_types.h +++ b/openair2/COMMON/pdcp_messages_types.h @@ -88,18 +88,18 @@ typedef struct NRRrcDcchDataReq_s { uint8_t gNB_index; } NRRrcDcchDataReq; +#include "openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_data.h" + typedef struct NRRrcDcchDataInd_s { uint32_t frame; uint8_t dcch_index; uint32_t sdu_size; uint8_t *sdu_p; - uint16_t rnti; - uint8_t module_id; - uint8_t gNB_index; // LG: needed in UE - /* these three variables are needed for RRC to check integrity of the PDCP SDU */ - uint32_t mac; - uint32_t header; - uint32_t count; + uint16_t rnti; + uint8_t module_id; + uint8_t gNB_index; // LG: needed in UE + /* 'msg_integrity' is needed for RRC to check integrity of the PDCP SDU */ + nr_pdcp_integrity_data_t msg_integrity; } NRRrcDcchDataInd; typedef struct RrcPcchDataReq_s { diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index 7e38c4fa9d..98162d003c 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -55,8 +55,6 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, int sdap_header_size = 0; int rx_deliv_sn; uint32_t rx_deliv_hfn; - uint32_t mac = 0; - uint32_t header = 0; if (entity->entity_suspended) { LOG_W(PDCP, "PDCP entity %d is suspended. Quit RX procedure.\n", entity->rb_id); @@ -123,19 +121,14 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, rcvd_count = (rcvd_hfn << entity->sn_size) | rcvd_sn; + nr_pdcp_integrity_data_t msg_integrity = { 0 }; + /* the MAC-I/header/rcvd_count is needed by some RRC procedures, store it */ if (entity->has_integrity || entity->type == NR_PDCP_SRB) { - mac = (uint32_t)buffer[size-4] - | ((uint32_t)buffer[size-3] << 8) - | ((uint32_t)buffer[size-2] << 16) - | ((uint32_t)buffer[size-1] << 24); - - /* higher byte of 'header' is its size, next 2 or 3 bytes are the header */ - header = (uint32_t)header_size << 24; - if (header_size == 2) - header |= (buffer[0] << 16) | (buffer[1] << 8); - else - header |= (buffer[0] << 16) | (buffer[1] << 8) | buffer[2]; + msg_integrity.count = rcvd_count; + memcpy(msg_integrity.mac, &buffer[size-4], 4); + msg_integrity.header_size = header_size; + memcpy(msg_integrity.header, buffer, header_size); } if (entity->has_ciphering) @@ -170,7 +163,7 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, sdu = nr_pdcp_new_sdu(rcvd_count, (char *)buffer + header_size, size - header_size - integrity_size, - mac, header); + &msg_integrity); entity->rx_list = nr_pdcp_sdu_list_add(entity->rx_list, sdu); entity->rx_size += size-header_size; @@ -187,7 +180,7 @@ static void nr_pdcp_entity_recv_pdu(nr_pdcp_entity_t *entity, nr_pdcp_sdu_t *cur = entity->rx_list; entity->deliver_sdu(entity->deliver_sdu_data, entity, cur->buffer, cur->size, - cur->mac, cur->header, cur->count); + &cur->msg_integrity); entity->rx_list = cur->next; entity->rx_size -= cur->size; entity->stats.txsdu_pkts++; @@ -299,33 +292,26 @@ static int nr_pdcp_entity_process_sdu(nr_pdcp_entity_t *entity, static bool nr_pdcp_entity_check_integrity(struct nr_pdcp_entity_t *entity, const uint8_t *buffer, int buffer_size, - uint32_t mac, - uint32_t header, - uint32_t count) + const nr_pdcp_integrity_data_t *msg_integrity) { if (!entity->has_integrity) return false; - int header_size = (header >> 24) & 0xff; + int header_size = msg_integrity->header_size; uint8_t b[buffer_size + header_size]; - b[0] = (header >> 16) & 0xff; - b[1] = (header >> 8) & 0xff; - if (header_size == 3) - b[2] = header & 0xff; + for (int i = 0; i < header_size; i++) + b[i] = msg_integrity->header[i]; + memcpy(b + header_size, buffer, buffer_size); - unsigned char integrity[4]; - entity->integrity(entity->integrity_context, integrity, + unsigned char mac[4]; + entity->integrity(entity->integrity_context, mac, b, buffer_size + header_size, - entity->rb_id, count, entity->is_gnb ? 0 : 1); - uint32_t nmac = (uint32_t)integrity[0] - | ((uint32_t)integrity[1] << 8) - | ((uint32_t)integrity[2] << 16) - | ((uint32_t)integrity[3] << 24); + entity->rb_id, msg_integrity->count, entity->is_gnb ? 0 : 1); - return nmac == mac; + return memcmp(mac, msg_integrity->mac, 4) == 0; } /* may be called several times, take care to clean previous settings */ @@ -410,7 +396,7 @@ static void check_t_reordering(nr_pdcp_entity_t *entity) nr_pdcp_sdu_t *cur = entity->rx_list; entity->deliver_sdu(entity->deliver_sdu_data, entity, cur->buffer, cur->size, - cur->mac, cur->header, cur->count); + &cur->msg_integrity); entity->rx_list = cur->next; entity->rx_size -= cur->size; entity->stats.txsdu_pkts++; @@ -424,7 +410,7 @@ static void check_t_reordering(nr_pdcp_entity_t *entity) nr_pdcp_sdu_t *cur = entity->rx_list; entity->deliver_sdu(entity->deliver_sdu_data, entity, cur->buffer, cur->size, - cur->mac, cur->header, cur->count); + &cur->msg_integrity); entity->rx_list = cur->next; entity->rx_size -= cur->size; entity->stats.txsdu_pkts++; @@ -455,7 +441,7 @@ static void deliver_all_sdus(nr_pdcp_entity_t *entity) nr_pdcp_sdu_t *cur = entity->rx_list; entity->deliver_sdu(entity->deliver_sdu_data, entity, cur->buffer, cur->size, - cur->mac, cur->header, cur->count); + &cur->msg_integrity); entity->rx_list = cur->next; entity->rx_size -= cur->size; entity->stats.txsdu_pkts++; @@ -577,7 +563,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( bool has_sdap_tx, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size, - uint32_t mac, uint32_t header, uint32_t count), + const nr_pdcp_integrity_data_t *msg_integrity), void *deliver_sdu_data, void (*deliver_pdu)(void *deliver_pdu_data, ue_id_t ue_id, int rb_id, char *buf, int size, int sdu_id), diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h index 058aabc87e..5d2fd56f70 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h @@ -107,16 +107,14 @@ typedef struct nr_pdcp_entity_t { /* check_integrity is used by RRC */ bool (*check_integrity)(struct nr_pdcp_entity_t *entity, const uint8_t *buffer, int buffer_length, - uint32_t mac, - uint32_t header, - uint32_t count); + const nr_pdcp_integrity_data_t *msg_integrity); void (*set_time)(struct nr_pdcp_entity_t *entity, uint64_t now); /* callbacks provided to the PDCP module */ void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size, - uint32_t mac, uint32_t header, uint32_t count); + const nr_pdcp_integrity_data_t *msg_integrity); void *deliver_sdu_data; void (*deliver_pdu)(void *deliver_pdu_data, ue_id_t ue_id, int rb_id, char *buf, int size, int sdu_id); @@ -188,7 +186,7 @@ nr_pdcp_entity_t *new_nr_pdcp_entity( bool has_sdap_tx, void (*deliver_sdu)(void *deliver_sdu_data, struct nr_pdcp_entity_t *entity, char *buf, int size, - uint32_t mac, uint32_t header, uint32_t count), + const nr_pdcp_integrity_data_t *msg_integrity), void *deliver_sdu_data, void (*deliver_pdu)(void *deliver_pdu_data, ue_id_t ue_id, int rb_id, char *buf, int size, int sdu_id), diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_data.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_data.h new file mode 100644 index 0000000000..6f14a7092a --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_integrity_data.h @@ -0,0 +1,34 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _NR_PDCP_INTEGRITY_DATA_H_ +#define _NR_PDCP_INTEGRITY_DATA_H_ + +#include + +typedef struct { + uint32_t count; + uint8_t mac[4]; + uint8_t header_size; + uint8_t header[3]; +} nr_pdcp_integrity_data_t; + +#endif /* _NR_PDCP_INTEGRITY_DATA_H_ */ diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index f0480f7be1..b3b756addc 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -659,7 +659,7 @@ uint64_t nr_pdcp_module_init(uint64_t _pdcp_optmask, int id) static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity, char *buf, int size, - uint32_t mac, uint32_t header, uint32_t count) + const nr_pdcp_integrity_data_t *msg_integrity) { nr_pdcp_ue_t *ue = _ue; int rb_id; @@ -743,7 +743,7 @@ static void deliver_pdu_drb_gnb(void *deliver_pdu_data, ue_id_t ue_id, int rb_id static void deliver_sdu_srb(void *_ue, nr_pdcp_entity_t *entity, char *buf, int size, - uint32_t mac, uint32_t header, uint32_t count) + const nr_pdcp_integrity_data_t *msg_integrity) { nr_pdcp_ue_t *ue = _ue; int srb_id; @@ -784,9 +784,7 @@ srb_found: NR_RRC_DCCH_DATA_IND(message_p).dcch_index = srb_id; NR_RRC_DCCH_DATA_IND(message_p).sdu_p = rrc_buffer_p; NR_RRC_DCCH_DATA_IND(message_p).sdu_size = size; - NR_RRC_DCCH_DATA_IND(message_p).mac = mac; - NR_RRC_DCCH_DATA_IND(message_p).header = header; - NR_RRC_DCCH_DATA_IND(message_p).count = count; + memcpy(&NR_RRC_DCCH_DATA_IND(message_p).msg_integrity, msg_integrity, sizeof(*msg_integrity)); ue_id_t ue_id = ue->ue_id; itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, message_p); } @@ -1069,9 +1067,7 @@ bool nr_pdcp_check_integrity_srb(ue_id_t ue_id, int srb_id, const uint8_t *msg, int msg_size, - uint32_t mac, - uint32_t header, - uint32_t count) + const nr_pdcp_integrity_data_t *msg_integrity) { nr_pdcp_ue_t *ue; nr_pdcp_entity_t *rb; @@ -1088,7 +1084,7 @@ bool nr_pdcp_check_integrity_srb(ue_id_t ue_id, return false; } - bool ret = rb->check_integrity(rb, msg, msg_size, mac, header, count); + bool ret = rb->check_integrity(rb, msg, msg_size, msg_integrity); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h index 2e87aa9023..99f7fcdc81 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h @@ -91,9 +91,7 @@ bool nr_pdcp_check_integrity_srb(ue_id_t ue_id, int srb_id, const uint8_t *msg, int msg_size, - uint32_t mac, - uint32_t header, - uint32_t count); + const nr_pdcp_integrity_data_t *msg_integrity); bool cu_f1u_data_req(protocol_ctxt_t *ctxt_pP, const srb_flag_t srb_flagP, diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c index 48af4b945a..783bc1c3bc 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.c @@ -25,7 +25,7 @@ #include nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size, - uint32_t mac, uint32_t header) + const nr_pdcp_integrity_data_t *msg_integrity) { nr_pdcp_sdu_t *ret = calloc(1, sizeof(nr_pdcp_sdu_t)); if (ret == NULL) @@ -36,8 +36,7 @@ nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size, exit(1); memcpy(ret->buffer, buffer, size); ret->size = size; - ret->mac = mac; - ret->header = header; + memcpy(&ret->msg_integrity, msg_integrity, sizeof(*msg_integrity)); return ret; } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h index 91d63fefe1..0452e71cfa 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_sdu.h @@ -24,24 +24,18 @@ #include +#include "nr_pdcp_integrity_data.h" + typedef struct nr_pdcp_sdu_t { - uint32_t count; - char *buffer; - int size; - uint32_t mac; - /* 'header' is decomposed into two parts: higher byte is the size of the - * header (2 or 3 bytes), then the next two or three bytes are the header - * so the size is: (header >> 24) & 0xff - * and first byte of header is: (header >> 16) & 0xff - * second byte of header is: (header >> 8) & 0xff - * and if there is a third, it is: header & 0xff - */ - uint32_t header; - struct nr_pdcp_sdu_t *next; + uint32_t count; + char *buffer; + int size; + nr_pdcp_integrity_data_t msg_integrity; + struct nr_pdcp_sdu_t *next; } nr_pdcp_sdu_t; nr_pdcp_sdu_t *nr_pdcp_new_sdu(uint32_t count, char *buffer, int size, - uint32_t mac, uint32_t header); + const nr_pdcp_integrity_data_t *msg_integrity); nr_pdcp_sdu_t *nr_pdcp_sdu_list_add(nr_pdcp_sdu_t *l, nr_pdcp_sdu_t *sdu); int nr_pdcp_sdu_in_list(nr_pdcp_sdu_t *l, uint32_t count); void nr_pdcp_free_sdu(nr_pdcp_sdu_t *sdu); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 20e941f90f..9e09db1a72 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1008,9 +1008,7 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, int srb_id, const uint8_t *msg, int msg_size, - uint32_t mac, - uint32_t header, - uint32_t count) + const nr_pdcp_integrity_data_t *msg_integrity) { LOG_I(NR_RRC, "Receiving from SRB1 (DL-DCCH), Processing securityModeCommand\n"); @@ -1072,7 +1070,7 @@ static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc, // the SecurityModeCommand message needs to pass the integrity protection check // for the UE to declare AS security to be activated - bool integrity_pass = nr_pdcp_check_integrity_srb(ue_rrc->ue_id, srb_id, msg, msg_size, mac, header, count); + bool integrity_pass = nr_pdcp_check_integrity_srb(ue_rrc->ue_id, srb_id, msg, msg_size, msg_integrity); if (!integrity_pass) { /* - continue using the configuration used prior to the reception of the SecurityModeCommand message, i.e. * neither apply integrity protection nor ciphering. @@ -1589,10 +1587,7 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, const uint8_t *const Buffer, size_t Buffer_size, const uint8_t gNB_indexP, - uint32_t mac, - uint32_t header, - uint32_t count) - + const nr_pdcp_integrity_data_t *msg_integrity) { NR_DL_DCCH_Message_t *dl_dcch_msg = NULL; if (Srb_id != 1 && Srb_id != 2) { @@ -1676,7 +1671,7 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, case NR_DL_DCCH_MessageType__c1_PR_securityModeCommand: LOG_I(NR_RRC, "Received securityModeCommand (gNB %d)\n", gNB_indexP); nr_rrc_ue_process_securityModeCommand(rrc, c1->choice.securityModeCommand, - Srb_id, Buffer, Buffer_size, mac, header, count); + Srb_id, Buffer, Buffer_size, msg_integrity); break; } } break; @@ -1782,9 +1777,7 @@ void *rrc_nrue(void *notUsed) NR_RRC_DCCH_DATA_IND(msg_p).sdu_p, NR_RRC_DCCH_DATA_IND(msg_p).sdu_size, NR_RRC_DCCH_DATA_IND(msg_p).gNB_index, - NR_RRC_DCCH_DATA_IND(msg_p).mac, - NR_RRC_DCCH_DATA_IND(msg_p).header, - NR_RRC_DCCH_DATA_IND(msg_p).count); + &NR_RRC_DCCH_DATA_IND(msg_p).msg_integrity); break; case NAS_KENB_REFRESH_REQ: From fbe2b65ee6b31006a63b76fb5aff1bf0b40a625d Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Wed, 27 Mar 2024 17:27:09 +0100 Subject: [PATCH 11/11] nr pdcp: small improvement: LOG after unlock Reduces time with lock acquired. --- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index b3b756addc..c2e49f7856 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -1050,8 +1050,8 @@ void nr_pdcp_config_set_security(ue_id_t ue_id, rb = nr_pdcp_get_rb(ue, rb_id, true); if (rb == NULL) { - LOG_E(PDCP, "no SRB found (ue_id %ld, rb_id %ld)\n", ue_id, rb_id); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + LOG_E(PDCP, "no SRB found (ue_id %ld, rb_id %ld)\n", ue_id, rb_id); return; } @@ -1079,8 +1079,8 @@ bool nr_pdcp_check_integrity_srb(ue_id_t ue_id, rb = nr_pdcp_get_rb(ue, srb_id, true); if (rb == NULL) { - LOG_E(PDCP, "no SRB found (ue_id %ld, rb_id %d)\n", ue_id, srb_id); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + LOG_E(PDCP, "no SRB found (ue_id %ld, rb_id %d)\n", ue_id, srb_id); return false; } @@ -1109,8 +1109,8 @@ bool nr_pdcp_data_req_srb(ue_id_t ue_id, rb = nr_pdcp_get_rb(ue, rb_id, true); if (rb == NULL) { - LOG_E(PDCP, "no SRB found (ue_id %ld, rb_id %ld)\n", ue_id, rb_id); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + LOG_E(PDCP, "no SRB found (ue_id %ld, rb_id %ld)\n", ue_id, rb_id); return 0; } @@ -1136,8 +1136,8 @@ void nr_pdcp_suspend_srb(ue_id_t ue_id, int srb_id) nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); nr_pdcp_entity_t *srb = nr_pdcp_get_rb(ue, srb_id, true); if (srb == NULL) { - LOG_E(PDCP, "Trying to suspend SRB with ID %d but it is not established\n", srb_id); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + LOG_E(PDCP, "Trying to suspend SRB with ID %d but it is not established\n", srb_id); return; } srb->suspend_entity(srb); @@ -1151,8 +1151,8 @@ void nr_pdcp_suspend_drb(ue_id_t ue_id, int drb_id) nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); nr_pdcp_entity_t *drb = nr_pdcp_get_rb(ue, drb_id, false); if (drb == NULL) { - LOG_E(PDCP, "Trying to suspend DRB with ID %d but it is not established\n", drb_id); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + LOG_E(PDCP, "Trying to suspend DRB with ID %d but it is not established\n", drb_id); return; } drb->suspend_entity(drb); @@ -1166,8 +1166,8 @@ void nr_pdcp_reconfigure_srb(ue_id_t ue_id, int srb_id, long t_Reordering) nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); nr_pdcp_entity_t *srb = nr_pdcp_get_rb(ue, srb_id, true); if (srb == NULL) { - LOG_E(PDCP, "Trying to reconfigure SRB with ID %d but it is not established\n", srb_id); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + LOG_E(PDCP, "Trying to reconfigure SRB with ID %d but it is not established\n", srb_id); return; } int decoded_t_reordering = decode_t_reordering(t_Reordering); @@ -1184,8 +1184,8 @@ void nr_pdcp_reconfigure_drb(ue_id_t ue_id, int drb_id, NR_PDCP_Config_t *pdcp_c nr_pdcp_ue_t *ue = nr_pdcp_manager_get_ue(nr_pdcp_ue_manager, ue_id); nr_pdcp_entity_t *drb = nr_pdcp_get_rb(ue, drb_id, false); if (drb == NULL) { - LOG_E(PDCP, "Trying to reconfigure DRB with ID %d but it is not established\n", drb_id); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + LOG_E(PDCP, "Trying to reconfigure DRB with ID %d but it is not established\n", drb_id); return; } if (pdcp_config) { @@ -1298,8 +1298,8 @@ bool nr_pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP, rb = nr_pdcp_get_rb(ue, rb_id, false); if (rb == NULL) { - LOG_E(PDCP, "[UE %lx] DRB %ld not found\n", rb_id, ue_id); nr_pdcp_manager_unlock(nr_pdcp_ue_manager); + LOG_E(PDCP, "[UE %lx] DRB %ld not found\n", ue_id, rb_id); return 0; }