OAI UE Mode complete ciphering bug
This commit is contained in:
@@ -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);
|
entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1);
|
||||||
|
|
||||||
if (entity->has_integrity) {
|
if (entity->has_integrity) {
|
||||||
unsigned char integrity[4];
|
unsigned char integrity[4] = {0};
|
||||||
entity->integrity(entity->integrity_context, integrity,
|
entity->integrity(entity->integrity_context, integrity,
|
||||||
buffer, size - integrity_size,
|
buffer, size - integrity_size,
|
||||||
entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1);
|
entity->rb_id, rcvd_count, entity->is_gnb ? 0 : 1);
|
||||||
if (memcmp(integrity, buffer + size - integrity_size, 4) != 0) {
|
if (memcmp(integrity, buffer + size - integrity_size, 4) != 0) {
|
||||||
LOG_E(PDCP, "discard NR PDU, integrity failed\n");
|
LOG_E(PDCP, "discard NR PDU, integrity failed\n");
|
||||||
// return;
|
|
||||||
entity->stats.rxpdu_dd_pkts++;
|
entity->stats.rxpdu_dd_pkts++;
|
||||||
entity->stats.rxpdu_dd_bytes += size;
|
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);
|
memcpy(buf + header_size, buffer, size);
|
||||||
|
|
||||||
if (entity->has_integrity)
|
if (entity->has_integrity){
|
||||||
|
uint8_t integrity[4] = {0};
|
||||||
entity->integrity(entity->integrity_context,
|
entity->integrity(entity->integrity_context,
|
||||||
(unsigned char *)buf + header_size + size,
|
integrity,
|
||||||
(unsigned char *)buf, header_size + size,
|
(unsigned char *)buf, header_size + size,
|
||||||
entity->rb_id, count, entity->is_gnb ? 1 : 0);
|
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
|
// set MAC-I to 0 for SRBs with integrity not active
|
||||||
else if (integrity_size == 4)
|
else if (integrity_size == 4)
|
||||||
memset(buf + header_size + size, 0, 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,
|
entity->cipher(entity->security_context,
|
||||||
(unsigned char *)buf + header_size, size + integrity_size,
|
(unsigned char *)buf + header_size, size + integrity_size,
|
||||||
entity->rb_id, count, entity->is_gnb ? 1 : 0);
|
entity->rb_id, count, entity->is_gnb ? 1 : 0);
|
||||||
|
} else {
|
||||||
|
entity->security_mode_completed = true;
|
||||||
|
}
|
||||||
|
|
||||||
entity->tx_next++;
|
entity->tx_next++;
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#ifndef _NR_PDCP_ENTITY_H_
|
#ifndef _NR_PDCP_ENTITY_H_
|
||||||
#define _NR_PDCP_ENTITY_H_
|
#define _NR_PDCP_ENTITY_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "nr_pdcp_sdu.h"
|
#include "nr_pdcp_sdu.h"
|
||||||
@@ -149,6 +150,19 @@ typedef struct nr_pdcp_entity_t {
|
|||||||
int rx_size;
|
int rx_size;
|
||||||
int rx_maxsize;
|
int rx_maxsize;
|
||||||
nr_pdcp_statistics_t stats;
|
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;
|
||||||
|
|
||||||
nr_pdcp_entity_t *new_nr_pdcp_entity(
|
nr_pdcp_entity_t *new_nr_pdcp_entity(
|
||||||
|
|||||||
@@ -1267,6 +1267,7 @@ void pdcp_config_set_security(
|
|||||||
ciphering_algorithm = security_modeP & 0x0f;
|
ciphering_algorithm = security_modeP & 0x0f;
|
||||||
rb->set_security(rb, integrity_algorithm, (char *)kRRCint_pP,
|
rb->set_security(rb, integrity_algorithm, (char *)kRRCint_pP,
|
||||||
ciphering_algorithm, (char *)kRRCenc_pP);
|
ciphering_algorithm, (char *)kRRCenc_pP);
|
||||||
|
rb->security_mode_completed = false;
|
||||||
} else {
|
} else {
|
||||||
LOG_E(PDCP, "%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__);
|
LOG_E(PDCP, "%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|||||||
@@ -54,14 +54,13 @@ void nr_pdcp_security_nea2_cipher(void *security_context,
|
|||||||
unsigned char *buffer, int length,
|
unsigned char *buffer, int length,
|
||||||
int bearer, int count, int direction)
|
int bearer, int count, int direction)
|
||||||
{
|
{
|
||||||
unsigned char t[16];
|
unsigned char t[16] = {0};
|
||||||
|
|
||||||
t[0] = (count >> 24) & 255;
|
t[0] = (count >> 24) & 255;
|
||||||
t[1] = (count >> 16) & 255;
|
t[1] = (count >> 16) & 255;
|
||||||
t[2] = (count >> 8) & 255;
|
t[2] = (count >> 8) & 255;
|
||||||
t[3] = (count ) & 255;
|
t[3] = (count ) & 255;
|
||||||
t[4] = ((bearer-1) << 3) | (direction << 2);
|
t[4] = ((bearer-1) << 3) | (direction << 2);
|
||||||
memset(&t[5], 0, 16-5);
|
|
||||||
|
|
||||||
nettle_ctr_crypt(security_context, nettle_aes128.encrypt,
|
nettle_ctr_crypt(security_context, nettle_aes128.encrypt,
|
||||||
nettle_aes128.block_size, t,
|
nettle_aes128.block_size, t,
|
||||||
|
|||||||
Reference in New Issue
Block a user