NSA: some work on security (for PDCP)
- compute correct kgNB - propagate properly NR security capabilities of an UE (involves: rrc, s1ap, x2ap)
This commit is contained in:
@@ -155,6 +155,11 @@ typedef struct security_capabilities_s {
|
|||||||
uint16_t integrity_algorithms;
|
uint16_t integrity_algorithms;
|
||||||
} security_capabilities_t;
|
} security_capabilities_t;
|
||||||
|
|
||||||
|
typedef struct nr_security_capabilities_s {
|
||||||
|
uint16_t encryption_algorithms;
|
||||||
|
uint16_t integrity_algorithms;
|
||||||
|
} nr_security_capabilities_t;
|
||||||
|
|
||||||
/* Provides the establishment cause for the RRC connection request as provided
|
/* Provides the establishment cause for the RRC connection request as provided
|
||||||
* by the upper layers. W.r.t. the cause value names: highPriorityAccess
|
* by the upper layers. W.r.t. the cause value names: highPriorityAccess
|
||||||
* concerns AC11..AC15, ‘mt’ stands for ‘Mobile Terminating’ and ‘mo’ for
|
* concerns AC11..AC15, ‘mt’ stands for ‘Mobile Terminating’ and ‘mo’ for
|
||||||
@@ -538,6 +543,9 @@ typedef struct s1ap_initial_context_setup_req_s {
|
|||||||
uint8_t nb_of_e_rabs;
|
uint8_t nb_of_e_rabs;
|
||||||
/* list of e_rab to be setup by RRC layers */
|
/* list of e_rab to be setup by RRC layers */
|
||||||
e_rab_t e_rab_param[S1AP_MAX_E_RAB];
|
e_rab_t e_rab_param[S1AP_MAX_E_RAB];
|
||||||
|
|
||||||
|
/* NR Security algorithms (if any, set to 0 if not present) */
|
||||||
|
nr_security_capabilities_t nr_security_capabilities;
|
||||||
} s1ap_initial_context_setup_req_t;
|
} s1ap_initial_context_setup_req_t;
|
||||||
|
|
||||||
typedef struct tai_plmn_identity_s {
|
typedef struct tai_plmn_identity_s {
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ typedef struct x2ap_ENDC_sgnb_addition_req_s {
|
|||||||
/* used for RRC->X2AP in source eNB */
|
/* used for RRC->X2AP in source eNB */
|
||||||
int rnti;
|
int rnti;
|
||||||
|
|
||||||
security_capabilities_t security_capabilities;
|
nr_security_capabilities_t security_capabilities;
|
||||||
|
|
||||||
/* SgNB Security Key */
|
/* SgNB Security Key */
|
||||||
uint8_t kgnb[32];
|
uint8_t kgnb[32];
|
||||||
|
|||||||
@@ -546,6 +546,13 @@ typedef struct rrc_gummei_s {
|
|||||||
uint16_t mme_group_id;
|
uint16_t mme_group_id;
|
||||||
} rrc_gummei_t;
|
} rrc_gummei_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t ciphering_algorithms;
|
||||||
|
uint16_t integrity_algorithms;
|
||||||
|
uint16_t sk_counter;
|
||||||
|
uint8_t kgNB[32];
|
||||||
|
} lte_rrc_nr_security_t;
|
||||||
|
|
||||||
typedef struct eNB_RRC_UE_s {
|
typedef struct eNB_RRC_UE_s {
|
||||||
uint8_t primaryCC_id;
|
uint8_t primaryCC_id;
|
||||||
LTE_SCellToAddMod_r10_t sCell_config[2];
|
LTE_SCellToAddMod_r10_t sCell_config[2];
|
||||||
@@ -615,6 +622,9 @@ typedef struct eNB_RRC_UE_s {
|
|||||||
|
|
||||||
security_capabilities_t security_capabilities;
|
security_capabilities_t security_capabilities;
|
||||||
|
|
||||||
|
/* security capabilities and settings for an UE in ENDC mode */
|
||||||
|
lte_rrc_nr_security_t nr_security;
|
||||||
|
|
||||||
int next_hop_chain_count;
|
int next_hop_chain_count;
|
||||||
|
|
||||||
uint8_t next_security_key[SECURITY_KEY_LENGTH];
|
uint8_t next_security_key[SECURITY_KEY_LENGTH];
|
||||||
|
|||||||
@@ -4665,11 +4665,20 @@ rrc_eNB_process_MeasurementReport(
|
|||||||
|
|
||||||
msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ);
|
msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ);
|
||||||
memset(&(X2AP_ENDC_SGNB_ADDITION_REQ(msg)), 0, sizeof(x2ap_ENDC_sgnb_addition_req_t));
|
memset(&(X2AP_ENDC_SGNB_ADDITION_REQ(msg)), 0, sizeof(x2ap_ENDC_sgnb_addition_req_t));
|
||||||
|
|
||||||
X2AP_ENDC_SGNB_ADDITION_REQ(msg).rnti = ctxt_pP->rnti;
|
X2AP_ENDC_SGNB_ADDITION_REQ(msg).rnti = ctxt_pP->rnti;
|
||||||
|
|
||||||
|
X2AP_ENDC_SGNB_ADDITION_REQ(msg).security_capabilities.encryption_algorithms = ue_context_pP->ue_context.nr_security.ciphering_algorithms;
|
||||||
|
X2AP_ENDC_SGNB_ADDITION_REQ(msg).security_capabilities.integrity_algorithms = ue_context_pP->ue_context.nr_security.integrity_algorithms;
|
||||||
|
|
||||||
|
memcpy(X2AP_ENDC_SGNB_ADDITION_REQ(msg).kgnb, ue_context_pP->ue_context.nr_security.kgNB, 32);
|
||||||
|
|
||||||
memcpy(X2AP_ENDC_SGNB_ADDITION_REQ(msg).rrc_buffer,enc_buf,enc_size);
|
memcpy(X2AP_ENDC_SGNB_ADDITION_REQ(msg).rrc_buffer,enc_buf,enc_size);
|
||||||
X2AP_ENDC_SGNB_ADDITION_REQ(msg).rrc_buffer_size = enc_size;
|
X2AP_ENDC_SGNB_ADDITION_REQ(msg).rrc_buffer_size = enc_size;
|
||||||
|
|
||||||
X2AP_ENDC_SGNB_ADDITION_REQ(msg).target_physCellId
|
X2AP_ENDC_SGNB_ADDITION_REQ(msg).target_physCellId
|
||||||
= measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[0]->physCellId;
|
= measResults2->measResultNeighCells->choice.measResultListEUTRA.list.array[0]->physCellId;
|
||||||
|
|
||||||
//For the moment we have a single E-RAB which will be the one to be added to the gNB
|
//For the moment we have a single E-RAB which will be the one to be added to the gNB
|
||||||
//Not sure how to select bearers to be added if there are multiple.
|
//Not sure how to select bearers to be added if there are multiple.
|
||||||
X2AP_ENDC_SGNB_ADDITION_REQ(msg).nb_e_rabs_tobeadded = 1;
|
X2AP_ENDC_SGNB_ADDITION_REQ(msg).nb_e_rabs_tobeadded = 1;
|
||||||
|
|||||||
@@ -1045,6 +1045,15 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ue_context_p->ue_context.nr_security.ciphering_algorithms = S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nr_security_capabilities.encryption_algorithms;
|
||||||
|
ue_context_p->ue_context.nr_security.integrity_algorithms = S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).nr_security_capabilities.integrity_algorithms;
|
||||||
|
/* let's initialize sk_counter to 0 */
|
||||||
|
ue_context_p->ue_context.nr_security.sk_counter = 0;
|
||||||
|
/* let's compute kgNB */
|
||||||
|
derive_skgNB(ue_context_p->ue_context.kenb,
|
||||||
|
ue_context_p->ue_context.nr_security.sk_counter,
|
||||||
|
ue_context_p->ue_context.nr_security.kgNB);
|
||||||
|
|
||||||
// in case, send the S1SP initial context response if it is not sent with the attach complete message
|
// in case, send the S1SP initial context response if it is not sent with the attach complete message
|
||||||
if (ue_context_p->ue_context.Status == RRC_RECONFIGURED) {
|
if (ue_context_p->ue_context.Status == RRC_RECONFIGURED) {
|
||||||
LOG_I(RRC, "Sending rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP, cause %ld\n", ue_context_p->ue_context.reestablishment_cause);
|
LOG_I(RRC, "Sending rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP, cause %ld\n", ue_context_p->ue_context.reestablishment_cause);
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ typedef enum {
|
|||||||
|
|
||||||
//int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keNB);
|
//int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t **keNB);
|
||||||
|
|
||||||
|
int derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB);
|
||||||
|
|
||||||
int derive_key(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
|
int derive_key(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
|
||||||
const uint8_t key[32], uint8_t **out);
|
const uint8_t key[32], uint8_t **out);
|
||||||
int nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id,
|
int nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id,
|
||||||
|
|||||||
@@ -159,3 +159,27 @@ int derive_keNB(const uint8_t key[32], const uint32_t nas_count, uint8_t **keNB)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
int derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB)
|
||||||
|
{
|
||||||
|
uint8_t *out;
|
||||||
|
uint8_t s[5];
|
||||||
|
|
||||||
|
/* FC is 0x1c (see 3gpp 33.401 annex A.15) */
|
||||||
|
s[0] = 0x1c;
|
||||||
|
|
||||||
|
/* put sk_counter */
|
||||||
|
s[1] = (sk_counter >> 8) & 0xff;
|
||||||
|
s[2] = sk_counter & 0xff;
|
||||||
|
|
||||||
|
/* put length of sk_counter (2) */
|
||||||
|
s[3] = 0x00;
|
||||||
|
s[4] = 0x02;
|
||||||
|
|
||||||
|
kdf(s, 5, keNB, 32, &out, 32);
|
||||||
|
|
||||||
|
memcpy(skgNB, out, 32);
|
||||||
|
free(out);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -864,22 +864,36 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
|
|||||||
BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.encryptionAlgorithms);
|
BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.encryptionAlgorithms);
|
||||||
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms =
|
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_capabilities.integrity_algorithms =
|
||||||
BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms);
|
BIT_STRING_to_uint16(&ie->value.choice.UESecurityCapabilities.integrityProtectionAlgorithms);
|
||||||
/* id-SecurityKey : Copy the security key */
|
|
||||||
} else {/* ie != NULL */
|
} else {/* ie != NULL */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* id-SecurityKey : Copy the security key */
|
||||||
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
|
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
|
||||||
S1AP_ProtocolIE_ID_id_SecurityKey, true);
|
S1AP_ProtocolIE_ID_id_SecurityKey, true);
|
||||||
|
|
||||||
if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
|
if (ie != NULL) { /* checked by macro but cppcheck doesn't see it */
|
||||||
memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key,
|
memcpy(&S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).security_key,
|
||||||
ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size);
|
ie->value.choice.SecurityKey.buf, ie->value.choice.SecurityKey.size);
|
||||||
itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
|
|
||||||
} else {/* ie != NULL */
|
} else {/* ie != NULL */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* id-NRUESecurityCapabilities */
|
||||||
|
S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_InitialContextSetupRequestIEs_t, ie, container,
|
||||||
|
S1AP_ProtocolIE_ID_id_NRUESecurityCapabilities, false);
|
||||||
|
if (ie != NULL) {
|
||||||
|
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms =
|
||||||
|
BIT_STRING_to_uint16(&ie->value.choice.NRUESecurityCapabilities.nRencryptionAlgorithms);
|
||||||
|
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms =
|
||||||
|
BIT_STRING_to_uint16(&ie->value.choice.NRUESecurityCapabilities.nRintegrityProtectionAlgorithms);
|
||||||
|
} else {
|
||||||
|
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.encryption_algorithms = 0;
|
||||||
|
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).nr_security_capabilities.integrity_algorithms = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
itti_send_msg_to_task(TASK_RRC_ENB, ue_desc_p->eNB_instance->instance, message_p);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user