OSA SECU harmonization

This commit is contained in:
mir
2023-05-26 12:35:33 +02:00
committed by Robert Schmidt
parent 7c7d54e463
commit c9012298de
53 changed files with 832 additions and 1778 deletions
+17 -26
View File
@@ -773,33 +773,25 @@ add_library(UTIL
${OPENAIR_DIR}/common/utils/time_stat.c
)
set(SECU_OSA_SRC
${OPENAIR2_DIR}/UTIL/OSA/osa_key_deriver.c
${OPENAIR2_DIR}/UTIL/OSA/osa_snow3g.c
${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eea.c
${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c
)
add_library(SECU_OSA ${SECU_OSA_SRC} $<TARGET_OBJECTS:ds> )
target_include_directories(SECU_OSA PRIVATE ${OPENAIR_DIR}/common/utils/ds/)
set(SECU_CN_SRC
set(SECURITY_SRC
${OPENAIR3_DIR}/SECU/secu_defs.c
${OPENAIR3_DIR}/SECU/kdf.c
${OPENAIR3_DIR}/SECU/aes_128_ctr.c
${OPENAIR3_DIR}/SECU/aes_128_cbc_cmac.c
${OPENAIR3_DIR}/SECU/aes_128_ecb.c
${OPENAIR3_DIR}/SECU/sha_256_hmac.c
${OPENAIR3_DIR}/SECU/rijndael.c
${OPENAIR3_DIR}/SECU/snow3g.c
${OPENAIR3_DIR}/SECU/key_nas_deriver.c
${OPENAIR3_DIR}/SECU/nas_stream_eea0.c
${OPENAIR3_DIR}/SECU/nas_stream_eea1.c
${OPENAIR3_DIR}/SECU/nas_stream_eia1.c
${OPENAIR3_DIR}/SECU/nas_stream_eea2.c
${OPENAIR3_DIR}/SECU/nas_stream_eia2.c
)
add_library(SECU_CN ${SECU_CN_SRC} $<TARGET_OBJECTS:ds>)
target_include_directories(SECU_CN PRIVATE ${OPENAIR_DIR}/common/utils/ds/)
add_library(SECURITY ${SECURITY_SRC} $<TARGET_OBJECTS:ds>)
target_include_directories(SECURITY PRIVATE ${OPENAIR_DIR}/common/utils/ds/)
# Physical Channel Procedures Scheduling
################################"
@@ -1350,8 +1342,8 @@ set(NR_PDCP_SRC
#these files should not be here, will be removed at some point when the
#computation is done directly inside nr_pdcp_integrity_nia1.c instead
#of reusing code of osa_stream_eia.c
${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c
${OPENAIR2_DIR}/UTIL/OSA/osa_snow3g.c
#${OPENAIR2_DIR}/UTIL/OSA/osa_stream_eia.c
#${OPENAIR2_DIR}/UTIL/OSA/osa_snow3g.c
)
set(NR_SDAP_SRC
@@ -1993,7 +1985,7 @@ add_library(LIB_5GNAS_GNB
)
target_include_directories(LIB_5GNAS_GNB PRIVATE ${OPENAIR_DIR}/common/utils/ds/)
target_link_libraries(LIB_5GNAS_GNB PRIVATE SECU_CN ${CRYPTO_LIBRARIES})
target_link_libraries(LIB_5GNAS_GNB PRIVATE SECURITY ${CRYPTO_LIBRARIES})
target_link_libraries(LIB_5GNAS_GNB PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
# Simulation library
@@ -2156,7 +2148,7 @@ add_dependencies(lte-softmodem oai_iqplayer)
target_link_libraries(lte-softmodem PRIVATE
-Wl,--start-group
lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB
lte_rrc nr_rrc s1ap m2ap x2ap m3ap GTPV1U SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_LIB SCHED_RU_LIB
PHY_COMMON PHY PHY_RU L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
${NAS_UE_LIB} ITTI SIMU SIMU_ETH
-Wl,--end-group z dl)
@@ -2165,7 +2157,6 @@ target_link_libraries(lte-softmodem PRIVATE pthread m CONFIG_LIB rt crypt ${CRYP
target_link_libraries(lte-softmodem PRIVATE ${T_LIB})
target_link_libraries(lte-softmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_executable(oairu
${OPENAIR_DIR}/executables/lte-ru.c
${OPENAIR_DIR}/executables/ru_control.c
@@ -2218,7 +2209,7 @@ endif()
target_link_libraries(lte-uesoftmodem PRIVATE
-Wl,--start-group
lte_rrc nr_rrc s1ap x2ap m2ap m3ap
SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
SECURITY UTIL HASHTABLE SCTP_CLIENT MME_APP SCHED_RU_LIB SCHED_UE_LIB PHY_COMMON
PHY_UE PHY_RU L2_UE L2_LTE SIMU SIMU_ETH NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_LTE_LIB
${NAS_UE_LIB} ITTI ${ATLAS_LIBRARIES}
-Wl,--end-group z dl)
@@ -2258,7 +2249,7 @@ add_executable(nr-softmodem
target_link_libraries(nr-softmodem PRIVATE
-Wl,--start-group
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECU_CN SECU_OSA
UTIL HASHTABLE SCTP_CLIENT SCHED_LIB SCHED_RU_LIB SCHED_NR_LIB PHY_NR PHY PHY_COMMON PHY_NR_COMMON PHY_RU GTPV1U SECURITY
ITTI ${NAS_UE_LIB} lte_rrc nr_rrc
ngap s1ap L2_LTE_NR L2_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB SIMU SIMU_ETH
x2ap f1ap m2ap m3ap e1ap
@@ -2293,7 +2284,7 @@ add_executable(nr-cuup
target_link_libraries(nr-cuup PRIVATE
CONFIG_LIB ITTI SCTP_CLIENT
GTPV1U e1ap e1_pdcp_if f1ap SIMU_ETH
SECU_OSA SECU_CN ${OPENSSL_LIBRARIES} crypt z sctp dl pthread)
SECURITY ${OPENSSL_LIBRARIES} crypt z sctp dl pthread)
target_link_libraries(nr-cuup PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
# nr-uesoftmodem is UE implementation
@@ -2320,7 +2311,7 @@ add_executable(nr-uesoftmodem
target_link_libraries(nr-uesoftmodem PRIVATE
-Wl,--start-group
nr_rrc SECU_CN SECU_OSA UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB
nr_rrc SECURITY UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB
PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB
NFAPI_USER_LIB MISC_NFAPI_NR_LIB
ITTI ${ATLAS_LIBRARIES} LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU SIMU_ETH
@@ -2464,7 +2455,7 @@ add_executable(nr_dlsim
${SHLIB_LOADER_SOURCES}
)
target_link_libraries(nr_dlsim PRIVATE
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECU_CN ngap -lz -Wl,--end-group
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl
)
target_link_libraries(nr_dlsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
@@ -2513,7 +2504,7 @@ if (ENABLE_LDPC_T1)
endif()
target_link_libraries(nr_ulsim PRIVATE
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECU_CN ngap -lz -Wl,--end-group
-Wl,--start-group UTIL SIMU SIMU_ETH PHY_COMMON PHY_NR_COMMON PHY_NR PHY_NR_UE SCHED_NR_LIB SCHED_NR_UE_LIB MAC_NR MAC_UE_NR MAC_NR_COMMON nr_rrc CONFIG_LIB L2_NR HASHTABLE x2ap SECURITY ngap -lz -Wl,--end-group
m pthread ${ATLAS_LIBRARIES} ${T_LIB} ITTI ${OPENSSL_LIBRARIES} dl
)
target_link_libraries(nr_ulsim PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
@@ -2552,7 +2543,7 @@ foreach(myExe s1ap
${OPENAIR3_DIR}/TEST/test_${myExe}.c
)
target_link_libraries (test_${myExe}
-Wl,--start-group SECU_CN UTIL -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} CONFIG_LIB
-Wl,--start-group SECURITY UTIL -Wl,--end-group m rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} CONFIG_LIB
)
endforeach(myExe)
@@ -2573,7 +2564,7 @@ if (${T_TRACER})
ITTI lte_rrc nr_rrc s1ap x2ap m2ap m3ap f1ap
params_libconfig oai_usrpdevif oai_bladerfdevif oai_lmssdrdevif oai_iqplayer
oai_eth_transpro oai_mobipass coding HASHTABLE UTIL OMG_SUMO
SECU_OSA SECU_CN SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL
SECURITY SCHED_LIB SCHED_NR_LIB SCHED_RU_LIB SCHED_UE_LIB SCHED_NR_UE_LIB default_sched remote_sched RAL
NFAPI_COMMON_LIB NFAPI_LIB NFAPI_PNF_LIB NFAPI_VNF_LIB NFAPI_USER_LIB
PHY_COMMON PHY PHY_UE PHY_NR PHY_NR_COMMON PHY_NR_UE PHY_RU PHY_MEX
L2 L2_LTE L2_NR L2_LTE_NR L2_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON MAC_NR MAC_UE_NR ngap
+3 -5
View File
@@ -98,9 +98,8 @@ nfapi_ue_release_request_body_t release_rntis;
instance_t DUuniqInstance=0;
instance_t CUuniqInstance=0;
int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
{
return 0;
}
int dummy_nr_ue_ul_indication(nr_uplink_indication_t *ul_info) { return(0); }
@@ -124,10 +123,9 @@ int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
return 0;
}
int nr_derive_key(int alg_type, uint8_t alg_id,
const uint8_t key[32], uint8_t **out)
void nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16])
{
return 0;
(void)alg_type;
}
void processSlotTX(void *arg) {}
+3 -5
View File
@@ -96,9 +96,8 @@ void deref_sched_response(int _)
exit(1);
}
int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
{
return 0;
}
void nr_rrc_ue_generate_RRCSetupRequest(module_id_t module_id, const uint8_t gNB_index)
@@ -120,10 +119,9 @@ int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index) {
return 0;
}
int nr_derive_key(int alg_type, uint8_t alg_id,
const uint8_t key[32], uint8_t **out)
void nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16])
{
return 0;
(void)alg_type;
}
nrUE_params_t nrUE_params;
+3 -5
View File
@@ -94,9 +94,8 @@ nfapi_ue_release_request_body_t release_rntis;
instance_t DUuniqInstance=0;
instance_t CUuniqInstance=0;
int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
{
return 0;
}
extern void fix_scd(NR_ServingCellConfig_t *scd);// forward declaration
@@ -133,10 +132,9 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(module_id_t module_idP,
nr_bler_struct nr_bler_data[NR_NUM_MCS];
int nr_derive_key(int alg_type, uint8_t alg_id,
const uint8_t key[32], uint8_t **out)
void nr_derive_key(int alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16])
{
return 0;
(void)alg_type;
}
void processSlotTX(void *arg) {}
+6 -5
View File
@@ -23,11 +23,12 @@
#include <arpa/inet.h>
#include "e1ap_api.h"
#include "UTIL/OSA/osa_defs.h"
#include "nr_pdcp/nr_pdcp_entity.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h"
#include "openair2/RRC/NR/cucp_cuup_if.h"
#include "openair2/RRC/LTE/MESSAGES/asn1_msg.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "openair3/ocp-gtpu/gtp_itf.h"
#include "e1ap_asnc.h"
#include "e1ap_common.h"
@@ -120,12 +121,12 @@ static int drb_config_N3gtpu_create(e1ap_bearer_setup_req_t * const req,
}
// Configure DRBs
uint8_t *kUPenc = NULL;
uint8_t *kUPint = NULL;
uint8_t kUPenc[16] = {0};
uint8_t kUPint[16] = {0};
nr_derive_key(UP_ENC_ALG, req->cipheringAlgorithm, (uint8_t *)req->encryptionKey, &kUPenc);
nr_derive_key(UP_ENC_ALG, req->cipheringAlgorithm, (uint8_t *)req->encryptionKey, kUPenc);
nr_derive_key(UP_INT_ALG, req->integrityProtectionAlgorithm, (uint8_t *)req->integrityProtectionKey, &kUPint);
nr_derive_key(UP_INT_ALG, req->integrityProtectionAlgorithm, (uint8_t *)req->integrityProtectionKey, kUPint);
nr_pdcp_e1_add_drbs(true, // set this to notify PDCP that his not UE
create_tunnel_req.ue_id,
+6 -30
View File
@@ -50,14 +50,13 @@
#include "common/openairinterface5g_limits.h"
#include "executables/lte-softmodem.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair2/RRC/NAS/nas_config.h"
#include "intertask_interface.h"
#include "openair3/S1AP/s1ap_eNB.h"
#include <pthread.h>
#include "pdcp.h"
# include "openair3/ocp-gtpu/gtp_itf.h"
#include "openair3/ocp-gtpu/gtp_itf.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "ENB_APP/enb_config.h"
@@ -2028,19 +2027,6 @@ pdcp_config_req_asn1(const protocol_ctxt_t *const ctxt_pP,
// pdcp_remove_UE(ctxt_pP);
}
/* Security keys */
if (pdcp_pP->kUPenc != NULL) {
free(pdcp_pP->kUPenc);
}
if (pdcp_pP->kRRCint != NULL) {
free(pdcp_pP->kRRCint);
}
if (pdcp_pP->kRRCenc != NULL) {
free(pdcp_pP->kRRCenc);
}
memset(pdcp_pP, 0, sizeof(pdcp_t));
break;
@@ -2105,9 +2091,11 @@ pdcp_config_set_security(
PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_pP),
pdcp_pP->cipheringAlgorithm,
pdcp_pP->integrityProtAlgorithm);
pdcp_pP->kRRCenc = kRRCenc;
pdcp_pP->kRRCint = kRRCint;
pdcp_pP->kUPenc = kUPenc;
kRRCenc != NULL ? memcpy(pdcp_pP->kRRCenc, kRRCenc, 32) : memset(pdcp_pP->kRRCenc, 0, 32);
kRRCint != NULL ? memcpy(pdcp_pP->kRRCint, kRRCint, 32) : memset(pdcp_pP->kRRCint, 0, 32);
kUPenc != NULL ? memcpy(pdcp_pP->kUPenc, kUPenc, 32) : memset(pdcp_pP->kUPenc, 0, 32);
/* Activate security */
pdcp_pP->security_activated = 1;
}
@@ -2328,18 +2316,6 @@ pdcp_free (
pdcp_t *pdcp_p = (pdcp_t *)pdcp_pP;
if (pdcp_p != NULL) {
if (pdcp_p->kUPenc != NULL) {
free(pdcp_p->kUPenc);
}
if (pdcp_p->kRRCint != NULL) {
free(pdcp_p->kRRCint);
}
if (pdcp_p->kRRCenc != NULL) {
free(pdcp_p->kRRCenc);
}
memset(pdcp_pP, 0, sizeof(pdcp_t));
free(pdcp_pP);
}
+6 -5
View File
@@ -45,6 +45,7 @@
#include "LTE_MBMS-SessionInfoList-r9.h"
#include "LTE_PMCH-InfoList-r9.h"
#include "openair3/SECU/secu_defs.h"
typedef rlc_op_status_t (*send_rlc_data_req_func_t)(const protocol_ctxt_t *const,
const srb_flag_t, const MBMS_flag_t,
@@ -161,17 +162,17 @@ typedef struct pdcp_s {
bool is_srb;
/* Configured security algorithms */
uint8_t cipheringAlgorithm;
uint8_t integrityProtAlgorithm;
eea_alg_id_e cipheringAlgorithm;
eia_alg_id_e integrityProtAlgorithm;
/* User-Plane encryption key
* Control-Plane RRC encryption key
* Control-Plane RRC integrity key
* These keys are configured by RRC layer
*/
uint8_t *kUPenc;
uint8_t *kRRCint;
uint8_t *kRRCenc;
uint8_t kUPenc[32];
uint8_t kRRCint[32];
uint8_t kRRCenc[32];
uint8_t security_activated;
+20 -18
View File
@@ -30,7 +30,6 @@
#include "assertions.h"
#include "common/utils/LOG/log.h"
#include "UTIL/OSA/osa_defs.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "executables/softmodem-common.h"
@@ -39,6 +38,8 @@
#include "pdcp.h"
#include "pdcp_primitives.h"
#include "openair3/SECU/secu_defs.h"
//-----------------------------------------------------------------------------
static
uint32_t pdcp_get_next_count_tx(
@@ -110,7 +111,7 @@ pdcp_apply_security(
)
{
uint8_t *buffer_encrypted = NULL;
stream_cipher_t encrypt_params;
nas_stream_cipher_t encrypt_params = {0};
DevAssert(pdcp_pP != NULL);
DevAssert(pdcp_pdu_buffer != NULL);
@@ -156,9 +157,7 @@ pdcp_apply_security(
buffer_encrypted = &pdcp_pdu_buffer[pdcp_header_len];
/* Apply ciphering if any requested */
stream_encrypt(pdcp_pP->cipheringAlgorithm,
&encrypt_params,
&buffer_encrypted);
stream_compute_encrypt(pdcp_pP->cipheringAlgorithm, &encrypt_params, buffer_encrypted);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_APPLY_SECURITY, VCD_FUNCTION_OUT);
@@ -180,7 +179,7 @@ pdcp_validate_security(
)
{
uint8_t *buffer_decrypted = NULL;
stream_cipher_t decrypt_params;
nas_stream_cipher_t decrypt_params = {0};
DevAssert(pdcp_pP != NULL);
@@ -199,19 +198,16 @@ pdcp_validate_security(
decrypt_params.key_length = 16;
if (srb_flagP) {
LOG_D(PDCP, "[OSA][RB %ld] %s Validating control-plane security\n",
rb_id, (pdcp_pP->is_ue != 0) ? "eNB -> UE" : "UE -> eNB");
LOG_D(PDCP, "[OSA][RB %ld] %s Validating control-plane security\n", rb_id, (pdcp_pP->is_ue != 0) ? "eNB -> UE" : "UE -> eNB");
decrypt_params.key = pdcp_pP->kRRCenc;// + 128;
} else {
LOG_D(PDCP, "[OSA][RB %ld] %s Validating user-plane security\n",
rb_id, (pdcp_pP->is_ue != 0) ? "eNB -> UE" : "UE -> eNB");
LOG_D(PDCP, "[OSA][RB %ld] %s Validating user-plane security\n", rb_id, (pdcp_pP->is_ue != 0) ? "eNB -> UE" : "UE -> eNB");
decrypt_params.key = pdcp_pP->kUPenc;// + 128;
}
/* Uncipher the block */
stream_decrypt(pdcp_pP->cipheringAlgorithm,
&decrypt_params,
&buffer_decrypted);
stream_compute_encrypt(pdcp_pP->cipheringAlgorithm, &decrypt_params, buffer_decrypted);
if (!IS_SOFTMODEM_IQPLAYER) {
if (srb_flagP) {
/* Now check the integrity of the complete PDU */
@@ -219,15 +215,21 @@ pdcp_validate_security(
decrypt_params.blength = sdu_buffer_size << 3;
decrypt_params.key = pdcp_pP->kRRCint + 16;// 128;
if (stream_check_integrity(pdcp_pP->integrityProtAlgorithm,
&decrypt_params,
&pdcp_pdu_buffer[sdu_buffer_size]) != 0) {
LOG_E(PDCP, "[OSA][RB %ld] %s failed to validate MAC-I (key %llx) of incoming PDU\n",
rb_id, (pdcp_pP->is_ue != 0) ? "UE" : "eNB",((long long unsigned int*)decrypt_params.key)[0]);
if (pdcp_pP->integrityProtAlgorithm != EIA0_ALG_ID) {
uint8_t result[4] = {0};
stream_compute_integrity(pdcp_pP->integrityProtAlgorithm, &decrypt_params, result);
if (memcmp(result, &pdcp_pdu_buffer[sdu_buffer_size], 4) != 0) {
LOG_E(PDCP,
"[OSA][RB %ld] %s failed to validate MAC-I (key %llx) of incoming PDU\n",
rb_id,
(pdcp_pP->is_ue != 0) ? "UE" : "eNB",
((long long unsigned int *)decrypt_params.key)[0]);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_VALIDATE_SECURITY, VCD_FUNCTION_OUT);
return -1;
}
}
}
} /* !IQPLAYER */
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_VALIDATE_SECURITY, VCD_FUNCTION_OUT);
-4
View File
@@ -52,8 +52,4 @@ void nr_pdcp_e1_add_drbs(eNB_flag_t enb_flag,
}
} else
LOG_W(PDCP, "%s with void list\n", __FUNCTION__);
if (kUPenc)
free(kUPenc);
if (kUPint)
free(kUPint);
}
@@ -26,13 +26,12 @@
#include <stdint.h>
#include <openssl/cmac.h>
#include "UTIL/OSA/osa_defs.h"
int stream_compute_integrity_eia1(stream_cipher_t *stream_cipher, uint8_t out[4]);
#include "openair3/SECU/secu_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
void *nr_pdcp_integrity_nia1_init(unsigned char *integrity_key)
{
stream_cipher_t *ret;
nas_stream_cipher_t *ret;
ret = calloc(1, sizeof(*ret)); if (ret == NULL) abort();
ret->key = malloc(16); if (ret->key == NULL) abort();
@@ -47,7 +46,7 @@ void nr_pdcp_integrity_nia1_integrity(void *integrity_context,
unsigned char *buffer, int length,
int bearer, int count, int direction)
{
stream_cipher_t *ctx = integrity_context;
nas_stream_cipher_t *ctx = integrity_context;
ctx->message = buffer;
ctx->count = count;
@@ -55,12 +54,12 @@ void nr_pdcp_integrity_nia1_integrity(void *integrity_context,
ctx->direction = direction;
ctx->blength = length * 8;
stream_compute_integrity_eia1(ctx, out);
stream_compute_integrity(EIA1_128_ALG_ID, ctx, out);
}
void nr_pdcp_integrity_nia1_free_integrity(void *integrity_context)
{
stream_cipher_t *ctx = integrity_context;
nas_stream_cipher_t *ctx = integrity_context;
free(ctx->key);
free(ctx);
}
@@ -920,10 +920,6 @@ void nr_pdcp_add_srbs(eNB_flag_t enb_flag, ue_id_t rntiMaybeUEid, NR_SRB_ToAddMo
}
} else
LOG_W(PDCP, "nr_pdcp_add_srbs() with void list\n");
if (kRRCenc)
free(kRRCenc);
if (kRRCint)
free(kRRCint);
}
void nr_pdcp_add_drbs(eNB_flag_t enb_flag,
@@ -941,10 +937,6 @@ void nr_pdcp_add_drbs(eNB_flag_t enb_flag,
}
} else
LOG_W(PDCP, "nr_pdcp_add_drbs() with void list\n");
if (kUPenc)
free(kUPenc);
if (kUPint)
free(kUPint);
}
/* Dummy function due to dependency from LTE libraries */
+1 -1
View File
@@ -104,7 +104,7 @@
#include "common/ran_context.h"
#include "secu_defs.h"
#include "key_nas_deriver.h"
#if !defined (msg)
#define msg printf
+16 -19
View File
@@ -73,7 +73,7 @@
#include "rrc_UE_ral.h"
#endif
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "pdcp.h"
#include "plmn_data.h"
@@ -1246,12 +1246,11 @@ rrc_ue_process_radioResourceConfigDedicated(
// Establish SRBs if present
// loop through SRBToAddModList
if (radioResourceConfigDedicated->srb_ToAddModList) {
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
derive_key_rrc_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCenc);
derive_key_rrc_int(UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm,
UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCint);
uint8_t kRRCenc[32] = {0};
uint8_t kRRCint[32] = {0};
derive_key_nas(RRC_ENC_ALG, UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm, UE_rrc_inst[ctxt_pP->module_id].kenb, kRRCenc);
derive_key_nas(RRC_INT_ALG, UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm, UE_rrc_inst[ctxt_pP->module_id].kenb, kRRCint);
// Refresh SRBs
rrc_pdcp_config_asn1_req(ctxt_pP,
radioResourceConfigDedicated->srb_ToAddModList,
@@ -1397,9 +1396,9 @@ rrc_ue_process_radioResourceConfigDedicated(
LOG_I(RRC,"[UE %d] default DRB = %ld\n",ctxt_pP->module_id, *UE_rrc_inst[ctxt_pP->module_id].defaultDRB);
}
uint8_t *kUPenc = NULL;
derive_key_up_enc(UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm,
UE_rrc_inst[ctxt_pP->module_id].kenb, &kUPenc);
uint8_t kUPenc[32] = {0};
derive_key_nas(UP_ENC_ALG, UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm, UE_rrc_inst[ctxt_pP->module_id].kenb, kUPenc);
// Refresh DRBs
rrc_pdcp_config_asn1_req(ctxt_pP,
(LTE_SRB_ToAddModList_t *)NULL,
@@ -1549,9 +1548,9 @@ rrc_ue_process_securityModeCommand(
ul_dcch_msg.message.choice.c1.present = LTE_UL_DCCH_MessageType__c1_PR_securityModeFailure;
}
uint8_t *kRRCenc = NULL;
uint8_t *kUPenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t kRRCenc[32] = {0};
uint8_t kUPenc[32] = {0};
uint8_t kRRCint[32] = {0};
pdcp_t *pdcp_p = NULL;
hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
hashtable_rc_t h_rc;
@@ -1577,12 +1576,10 @@ rrc_ue_process_securityModeCommand(
UE_rrc_inst[ctxt_pP->module_id].kenb[20], UE_rrc_inst[ctxt_pP->module_id].kenb[21], UE_rrc_inst[ctxt_pP->module_id].kenb[22], UE_rrc_inst[ctxt_pP->module_id].kenb[23],
UE_rrc_inst[ctxt_pP->module_id].kenb[24], UE_rrc_inst[ctxt_pP->module_id].kenb[25], UE_rrc_inst[ctxt_pP->module_id].kenb[26], UE_rrc_inst[ctxt_pP->module_id].kenb[27],
UE_rrc_inst[ctxt_pP->module_id].kenb[28], UE_rrc_inst[ctxt_pP->module_id].kenb[29], UE_rrc_inst[ctxt_pP->module_id].kenb[30], UE_rrc_inst[ctxt_pP->module_id].kenb[31]);
derive_key_rrc_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCenc);
derive_key_rrc_int(UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm,
UE_rrc_inst[ctxt_pP->module_id].kenb, &kRRCint);
derive_key_up_enc(UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm,
UE_rrc_inst[ctxt_pP->module_id].kenb, &kUPenc);
derive_key_nas(RRC_ENC_ALG, UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm, UE_rrc_inst[ctxt_pP->module_id].kenb, kRRCenc);
derive_key_nas(RRC_INT_ALG, UE_rrc_inst[ctxt_pP->module_id].integrity_algorithm, UE_rrc_inst[ctxt_pP->module_id].kenb, kRRCint);
derive_key_nas(UP_ENC_ALG, UE_rrc_inst[ctxt_pP->module_id].ciphering_algorithm, UE_rrc_inst[ctxt_pP->module_id].kenb, kUPenc);
if (securityMode != 0xff) {
pdcp_config_set_security(ctxt_pP, pdcp_p, 0, 0,
+11 -18
View File
@@ -44,7 +44,6 @@
#include "RRC/LTE/MESSAGES/asn1_msg.h"
#include "LTE_RRCConnectionRequest.h"
#include "LTE_RRCConnectionReestablishmentRequest.h"
//#include "ReestablishmentCause.h"
#include "LTE_BCCH-BCH-Message.h"
#include "LTE_UL-CCCH-Message.h"
#include "LTE_DL-CCCH-Message.h"
@@ -81,15 +80,14 @@
#include "RRC/NAS/nas_config.h"
#include "RRC/NAS/rb_config.h"
#include "UTIL/OSA/osa_defs.h"
#include "rrc_eNB_S1AP.h"
#include "rrc_eNB_GTPV1U.h"
#include "rrc_eNB_M2AP.h"
#include "pdcp.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "openair3/SECU/secu_defs.h"
#include "openair3/ocp-gtpu/gtp_itf.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "intertask_interface.h"
#include "softmodem-common.h"
@@ -114,8 +112,9 @@ mui_t rrc_eNB_mui = 0;
extern uint32_t to_earfcn_DL(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw);
extern int rrc_eNB_process_security(const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, security_capabilities_t *security_capabilities_pP);
extern void process_eNB_security_key (const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, uint8_t *security_key_pP);
extern int derive_keNB_star(const uint8_t *kenb_32, const uint16_t pci, const uint32_t earfcn_dl, const bool is_rel8_only, uint8_t *kenb_star);
extern void process_eNB_security_key(const protocol_ctxt_t *const ctxt_pP,
rrc_eNB_ue_context_t *const ue_context_pP,
uint8_t *security_key_pP);
extern int rrc_eNB_generate_RRCConnectionReconfiguration_endc(protocol_ctxt_t *ctxt, rrc_eNB_ue_context_t *ue_context, unsigned char *buffer, int buffer_size, OCTET_STRING_t *scg_group_config,
OCTET_STRING_t *scg_RB_config);
extern struct rrc_eNB_ue_context_s *get_first_ue_context(eNB_RRC_INST *rrc_instance_pP);
@@ -5145,9 +5144,9 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
int drb_id;
int oip_ifup = 0;
int dest_ip_offset = 0;
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t *kUPenc = NULL;
uint8_t kRRCenc[32] = {0};
uint8_t kRRCint[32] = {0};
uint8_t kUPenc[32] = {0};
LTE_DRB_ToAddModList_t *DRB_configList = ue_context_pP->ue_context.DRB_configList2[xid];
LTE_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList2[xid];
LTE_DRB_ToReleaseList_t *DRB_Release_configList2 = ue_context_pP->ue_context.DRB_Release_configList2[xid];
@@ -5178,17 +5177,11 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
/* Derive the keys from kenb */
if (DRB_configList != NULL) {
derive_key_up_enc(ue_context_pP->ue_context.ciphering_algorithm,
ue_context_pP->ue_context.kenb,
&kUPenc);
derive_key_nas(UP_ENC_ALG, ue_context_pP->ue_context.ciphering_algorithm, ue_context_pP->ue_context.kenb, kUPenc);
}
derive_key_rrc_enc(ue_context_pP->ue_context.ciphering_algorithm,
ue_context_pP->ue_context.kenb,
&kRRCenc);
derive_key_rrc_int(ue_context_pP->ue_context.integrity_algorithm,
ue_context_pP->ue_context.kenb,
&kRRCint);
derive_key_nas(RRC_ENC_ALG, ue_context_pP->ue_context.ciphering_algorithm, ue_context_pP->ue_context.kenb, kRRCenc);
derive_key_nas(RRC_INT_ALG, ue_context_pP->ue_context.integrity_algorithm, ue_context_pP->ue_context.kenb, kRRCint);
/* Refresh SRBs/DRBs */
rrc_pdcp_config_asn1_req(ctxt_pP,
SRB_configList, // NULL,
+12 -15
View File
@@ -46,12 +46,14 @@
#include "pdcp.h"
#include "pdcp_primitives.h"
#include "UTIL/OSA/osa_defs.h"
#include "LTE_UERadioAccessCapabilityInformation.h"
#include "openair3/ocp-gtpu/gtp_itf.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "openair3/SECU/secu_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "RRC/LTE/rrc_eNB_GTPV1U.h"
#include "TLVDecoder.h"
@@ -485,9 +487,9 @@ rrc_pdcp_config_security(
//------------------------------------------------------------------------------
{
LTE_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList;
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t *kUPenc = NULL;
uint8_t kRRCenc[32] = {0};
uint8_t kRRCint[32] = {0};
uint8_t kUPenc[32] = {0};
pdcp_t *pdcp_p = NULL;
static int print_keys= 1;
hashtable_rc_t h_rc;
@@ -495,19 +497,13 @@ rrc_pdcp_config_security(
/* Derive the keys from kenb */
if (SRB_configList != NULL) {
derive_key_up_enc(ue_context_pP->ue_context.ciphering_algorithm,
ue_context_pP->ue_context.kenb,
&kUPenc);
derive_key_nas(UP_ENC_ALG, ue_context_pP->ue_context.ciphering_algorithm, ue_context_pP->ue_context.kenb, kUPenc);
}
derive_key_rrc_enc(ue_context_pP->ue_context.ciphering_algorithm,
ue_context_pP->ue_context.kenb,
&kRRCenc);
derive_key_rrc_int(ue_context_pP->ue_context.integrity_algorithm,
ue_context_pP->ue_context.kenb,
&kRRCint);
derive_key_nas(RRC_ENC_ALG, ue_context_pP->ue_context.ciphering_algorithm, ue_context_pP->ue_context.kenb, kRRCenc);
derive_key_nas(RRC_INT_ALG, ue_context_pP->ue_context.integrity_algorithm, ue_context_pP->ue_context.kenb, kRRCint);
if (!IS_SOFTMODEM_IQPLAYER) {
SET_LOG_DUMP(DEBUG_SECURITY) ;
SET_LOG_DUMP(DEBUG_SECURITY);
}
@@ -953,6 +949,7 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char
&ctxt,
ue_context_p,
S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).security_key);
{
uint8_t send_security_mode_command = true;
rrc_pdcp_config_security(
+3 -1
View File
@@ -46,7 +46,9 @@
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "asn1_msg.h"
#include "../nr_rrc_proto.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "RRC/NR/nr_rrc_extern.h"
#include "NR_DL-CCCH-Message.h"
#include "NR_UL-CCCH-Message.h"
+12 -9
View File
@@ -29,7 +29,8 @@
#include "nr_rrc_proto.h"
#include "nr_rrc_extern.h"
#include "openair2/COMMON/e1ap_messages_types.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "nr_pdcp/nr_pdcp_entity.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h"
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
@@ -38,6 +39,7 @@
#include "common/ran_context.h"
#include "openair2/F1AP/f1ap_common.h"
#include "openair2/E1AP/e1ap_common.h"
extern RAN_CONTEXT_t RC;
void fill_e1ap_bearer_setup_resp(e1ap_bearer_setup_resp_t *resp,
@@ -134,18 +136,19 @@ static int drb_config_gtpu_create(const protocol_ctxt_t *const ctxt_p,
nr_rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(ctxt_p, &create_tunnel_resp, 0);
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t *kUPenc = NULL;
uint8_t *kUPint = NULL;
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kUPenc[16] = {0};
uint8_t kUPint[16] = {0};
/* Derive the keys from kgnb */
if (DRB_configList != NULL) {
nr_derive_key_up_enc(UE->ciphering_algorithm, UE->kgnb, &kUPenc);
nr_derive_key_up_int(UE->integrity_algorithm, UE->kgnb, &kUPint);
nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kUPenc);
nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, kUPint);
}
nr_derive_key_rrc_enc(UE->ciphering_algorithm, UE->kgnb, &kRRCenc);
nr_derive_key_rrc_int(UE->integrity_algorithm, UE->kgnb, &kRRCint);
nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kRRCenc);
nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, kRRCint);
/* Refresh SRBs/DRBs */
LOG_D(NR_RRC, "Configuring PDCP DRBs/SRBs for UE %x\n", UE->rnti);
+2 -1
View File
@@ -29,7 +29,8 @@
#include "nr_rrc_extern.h"
#include "cucp_cuup_if.h"
#include "openair2/COMMON/e1ap_messages_types.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/secu_defs.h"
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
#include "common/ran_context.h"
+21 -21
View File
@@ -75,7 +75,7 @@
#include "RRC/NAS/nas_config.h"
#include "RRC/NAS/rb_config.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/secu_defs.h"
#include "rrc_gNB_NGAP.h"
@@ -90,6 +90,7 @@
#include "executables/softmodem-common.h"
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
#include <openair2/X2AP/x2ap_eNB.h>
#include <openair3/SECU/key_nas_deriver.h>
#include <openair3/ocp-gtpu/gtp_itf.h>
#include <openair2/RRC/NR/nr_rrc_proto.h>
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_e1_api.h"
@@ -1035,31 +1036,30 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
static void rrc_gNB_process_RRCReconfigurationComplete(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP, const uint8_t xid)
{
int drb_id;
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t *kUPenc = NULL;
uint8_t *kUPint = NULL;
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
NR_DRB_ToAddModList_t *DRB_configList = ue_p->DRB_configList2[xid];
NR_SRB_ToAddModList_t *SRB_configList = ue_p->SRB_configList2[xid];
NR_DRB_ToReleaseList_t *DRB_Release_configList2 = ue_p->DRB_Release_configList2[xid];
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kUPenc[16] = {0};
uint8_t kUPint[16] = {0};
NR_DRB_ToAddModList_t *DRB_configList = ue_context_pP->ue_context.DRB_configList2[xid];
NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList2[xid];
NR_DRB_ToReleaseList_t *DRB_Release_configList2 = ue_context_pP->ue_context.DRB_Release_configList2[xid];
NR_DRB_Identity_t *drb_id_p = NULL;
// uint8_t nr_DRB2LCHAN[8];
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
ue_p->ue_reestablishment_timer = 0;
/* Derive the keys from kgnb */
if (DRB_configList != NULL) {
nr_derive_key_up_enc(ue_p->ciphering_algorithm, ue_p->kgnb, &kUPenc);
nr_derive_key_up_int(ue_p->integrity_algorithm, ue_p->kgnb, &kUPint);
nr_derive_key(UP_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kUPenc);
nr_derive_key(UP_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, kUPint);
}
nr_derive_key_rrc_enc(ue_p->ciphering_algorithm, ue_p->kgnb, &kRRCenc);
nr_derive_key_rrc_int(ue_p->integrity_algorithm, ue_p->kgnb, &kRRCint);
nr_derive_key(RRC_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kRRCenc);
nr_derive_key(RRC_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, kRRCint);
/* Refresh SRBs/DRBs */
LOG_D(NR_RRC, "Configuring PDCP DRBs/SRBs for UE %04x\n", ue_p->rnti);
ue_id_t reestablish_ue_id = 0;
if (DRB_configList && DRB_configList->list.array[0]->reestablishPDCP && *DRB_configList->list.array[0]->reestablishPDCP == NR_DRB_ToAddMod__reestablishPDCP_true) {
for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) {
@@ -1226,16 +1226,16 @@ void rrc_gNB_generate_RRCReestablishment(const protocol_ctxt_t *ctxt_pP,
LOG_I(NR_RRC, "[RAPROC] UE %04x Logical Channel DL-DCCH, Generating NR_RRCReestablishment (bytes %d)\n", ue_p->rnti, size);
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t *kUPenc = NULL;
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kUPenc[16] = {0};
/* Derive the keys from kgnb */
if (SRB_configList != NULL) {
nr_derive_key_up_enc(ue_p->ciphering_algorithm, ue_p->kgnb, &kUPenc);
nr_derive_key(UP_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kUPenc);
}
nr_derive_key_rrc_enc(ue_p->ciphering_algorithm, ue_p->kgnb, &kRRCenc);
nr_derive_key_rrc_int(ue_p->integrity_algorithm, ue_p->kgnb, &kRRCint);
nr_derive_key(RRC_ENC_ALG, ue_p->ciphering_algorithm, ue_p->kgnb, kRRCenc);
nr_derive_key(RRC_INT_ALG, ue_p->integrity_algorithm, ue_p->kgnb, kRRCint);
/* Configure SRB1 for UE */
if (*SRB_configList != NULL) {
+9 -7
View File
@@ -47,7 +47,8 @@
#include "S1AP_NAS-PDU.h"
#include "executables/softmodem-common.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "ngap_gNB_defs.h"
#include "ngap_gNB_ue_context.h"
#include "ngap_gNB_management_procedures.h"
@@ -126,20 +127,21 @@ nr_rrc_pdcp_config_security(
{
NR_SRB_ToAddModList_t *SRB_configList = ue_context_pP->ue_context.SRB_configList;
(void)SRB_configList;
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
uint8_t *kUPenc = NULL;
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
uint8_t kUPenc[16] = {0};
//uint8_t *k_kdf = NULL;
static int print_keys= 1;
gNB_RRC_UE_t *UE = &ue_context_pP->ue_context;
/* Derive the keys from kgnb */
if (UE->Srb[1].Active || UE->Srb[2].Active) {
nr_derive_key_up_enc(UE->ciphering_algorithm, UE->kgnb, &kUPenc);
nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kUPenc);
}
nr_derive_key_rrc_enc(UE->ciphering_algorithm, UE->kgnb, &kRRCenc);
nr_derive_key_rrc_int(UE->integrity_algorithm, UE->kgnb, &kRRCint);
nr_derive_key(RRC_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kRRCenc);
nr_derive_key(RRC_INT_ALG, UE->integrity_algorithm, UE->kgnb, kRRCint);
if (!IS_SOFTMODEM_IQPLAYER) {
SET_LOG_DUMP(DEBUG_SECURITY) ;
}
+7 -5
View File
@@ -43,7 +43,9 @@
#include "executables/nr-softmodem.h"
#include <openair2/RRC/NR/rrc_gNB_UE_context.h>
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/secu_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include <openair2/RRC/NR/nr_rrc_proto.h>
#include "nr_pdcp/nr_pdcp_oai_api.h"
#include "MESSAGES/asn1_msg.h"
@@ -121,8 +123,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a
gtpv1u_enb_create_tunnel_req_t create_tunnel_req;
gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp;
protocol_ctxt_t ctxt={0};
unsigned char *kUPenc = NULL;
unsigned char *kUPint = NULL;
uint8_t kUPenc[16] = {0};
uint8_t kUPint[16] = {0};
int i;
gNB_RRC_UE_t *UE = &ue_context_p->ue_context;
@@ -212,8 +214,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a
LOG_I(RRC, "selecting integrity algorithm %d\n", UE->integrity_algorithm);
/* derive UP security key */
nr_derive_key_up_enc(UE->ciphering_algorithm, UE->kgnb, &kUPenc);
nr_derive_key_up_int(UE->integrity_algorithm, UE->kgnb, &kUPint);
nr_derive_key(UP_ENC_ALG, UE->ciphering_algorithm, UE->kgnb, kUPenc);
nr_derive_key(UP_INT_ALG, UE->integrity_algorithm, UE->kgnb, kUPint);
e_NR_CipheringAlgorithm cipher_algo;
switch (UE->ciphering_algorithm) {
+36 -20
View File
@@ -57,7 +57,9 @@
#include "nr-uesoftmodem.h"
#include "plmn_data.h"
#include "nr_pdcp/nr_pdcp_oai_api.h"
#include "UTIL/OSA/osa_defs.h"
#include "openair3/SECU/secu_defs.h"
#include "openair3/SECU/key_nas_deriver.h"
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
@@ -1522,18 +1524,22 @@ int8_t nr_rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const NR_SRB
ul_dcch_msg.message.choice.c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete;
}
uint8_t *kRRCenc = NULL;
uint8_t *kUPenc = NULL;
uint8_t *kRRCint = NULL;
nr_derive_key_up_enc(NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,
uint8_t kRRCenc[16] = {0};
uint8_t kUPenc[16] = {0};
uint8_t kRRCint[16] = {0};
nr_derive_key(UP_ENC_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
&kUPenc);
nr_derive_key_rrc_enc(NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,
kUPenc);
nr_derive_key(RRC_ENC_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
&kRRCenc);
nr_derive_key_rrc_int(NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm,
kRRCenc);
nr_derive_key(RRC_INT_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
&kRRCint);
kRRCint);
LOG_I(NR_RRC, "driving kRRCenc, kRRCint and kUPenc from KgNB="
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
@@ -1868,10 +1874,16 @@ nr_rrc_ue_establish_srb2(
}
}
uint8_t *kRRCenc = NULL;
uint8_t *kRRCint = NULL;
nr_derive_key_rrc_enc(ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, &kRRCenc);
nr_derive_key_rrc_int(ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, &kRRCint);
uint8_t kRRCenc[16] = {0};
uint8_t kRRCint[16] = {0};
nr_derive_key(RRC_ENC_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
kRRCenc);
nr_derive_key(RRC_INT_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
kRRCint);
// Refresh SRBs
nr_pdcp_add_srbs(ctxt_pP->enb_flag,
@@ -1959,12 +1971,16 @@ nr_rrc_ue_establish_srb2(
}
}
uint8_t *kUPenc = NULL;
uint8_t *kUPint = NULL;
NR_UE_RRC_INST_t *ue_rrc = &NR_UE_rrc_inst[ctxt_pP->module_id];
nr_derive_key_up_enc(ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, &kUPenc);
nr_derive_key_up_int(ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, &kUPint);
uint8_t kUPenc[16] = {0};
uint8_t kUPint[16] = {0};
nr_derive_key(UP_ENC_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].cipheringAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
kUPenc);
nr_derive_key(UP_INT_ALG,
NR_UE_rrc_inst[ctxt_pP->module_id].integrityProtAlgorithm,
NR_UE_rrc_inst[ctxt_pP->module_id].kgnb,
kUPint);
// Refresh DRBs
nr_pdcp_add_drbs(ctxt_pP->enb_flag,
-18
View File
@@ -1,18 +0,0 @@
OAISIM Security Algorithms v0.1
Dependencies:
- openssl >= 1.0.1
Compilation:
When compiling oaisim, add SECU=1 to enable security features. The makefile will
check for required dependencies and disable this feature if not all dependencies
are met.
OSA is based on 3GPP TS 33.401.
Note that only EEA2 and EIA2 algorithms are supported, SNOW-3G is not implemented.
Currently the kenb used to derive kRRCint, kRRCenc and kUPenc is composed of the
UE_id. In the future this parameter can be either obtained by deriving KASME received
from core epc (in the S1AP initial context setup request)
or configurable via command line or XML file.
-138
View File
@@ -1,138 +0,0 @@
/*
* 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
*/
/*!
* \file secu_defs.h
* \brief Openair security algorithms functions implementing 3GPP TS 33.401
* \note HMAC computations are done by openssl library
* \author Sebastien ROUX
* \date 2013
* \version 0.1
* @ingroup security
*/
#ifndef __UTIL_OSA_OSA_DEFS__H__
#define __UTIL_OSA_OSA_DEFS__H__
#define EIA0_ALG_ID 0x00
#define EIA1_128_ALG_ID 0x01
#define EIA2_128_ALG_ID 0x02
#define EEA0_ALG_ID EIA0_ALG_ID
#define EEA1_128_ALG_ID EIA1_128_ALG_ID
#define EEA2_128_ALG_ID EIA2_128_ALG_ID
#define SECU_DIRECTION_UPLINK 0
#define SECU_DIRECTION_DOWNLINK 1
typedef enum {
NAS_ENC_ALG = 0x01,
NAS_INT_ALG = 0x02,
RRC_ENC_ALG = 0x03,
RRC_INT_ALG = 0x04,
UP_ENC_ALG = 0x05,
UP_INT_ALG = 0x06
} algorithm_type_dist_t;
//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,
const uint8_t key[32], uint8_t **out);
int nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id,
const uint8_t key[32], uint8_t **out);
int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star);
//#define derive_key_nas_enc(aLGiD, kEY, kNAS) derive_key(NAS_ENC_ALG, aLGiD, kEY, kNAS)
//#define derive_key_nas_int(aLGiD, kEY, kNAS) derive_key(NAS_INT_ALG, aLGiD, kEY, kNAS)
#define derive_key_rrc_enc(aLGiD, kEY, kNAS) \
derive_key(RRC_ENC_ALG, aLGiD, kEY, kNAS)
#define derive_key_rrc_int(aLGiD, kEY, kNAS) \
derive_key(RRC_INT_ALG, aLGiD, kEY, kNAS)
#define derive_key_up_enc(aLGiD, kEY, kNAS) \
derive_key(UP_ENC_ALG, aLGiD, kEY, kNAS)
#define derive_key_up_int(aLGiD, kEY, kNAS) \
derive_key(UP_INT_ALG, aLGiD, kEY, kNAS)
// 5G SA
#define nr_derive_key_rrc_enc(aLGiD, kEY, kRRC) \
nr_derive_key(RRC_ENC_ALG, aLGiD, kEY, kRRC)
#define nr_derive_key_rrc_int(aLGiD, kEY, kRRC) \
nr_derive_key(RRC_INT_ALG, aLGiD, kEY, kRRC)
#define nr_derive_key_up_enc(aLGiD, kEY, kUP) \
nr_derive_key(UP_ENC_ALG, aLGiD, kEY, kUP)
#define nr_derive_key_up_int(aLGiD, kEY, kUP) \
nr_derive_key(UP_INT_ALG, aLGiD, kEY, kUP)
typedef struct {
uint8_t *key;
uint32_t key_length;
uint32_t count;
uint8_t bearer;
uint8_t direction;
uint8_t *message;
/* length in bits */
uint32_t blength;
} stream_cipher_t;
/*!
* @brief Encrypt/Decrypt a block of data based on the provided algorithm
* @param[in] algorithm Algorithm used to encrypt the data
* Possible values are:
* - EIA0_ALG_ID for NULL encryption
* - EIA1_128_ALG_ID for SNOW-3G encryption (not avalaible right now)
* - EIA2_128_ALG_ID for 128 bits AES LTE encryption
* @param[in] stream_cipher All parameters used to compute the encrypted block of data
* @param[out] out The encrypted block of data dynamically allocated
* @return 0 if everything OK, -1 if something failed
*/
int stream_encrypt(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t **out);
#define stream_decrypt stream_encrypt
int stream_compute_integrity(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t out[4]);
/*!
* @brief Decrypt a block of data based on the provided algorithm
* @param[in] algorithm Algorithm used to encrypt the data
* Possible values are:
* - EIA0_ALG_ID for NULL encryption
* - EIA1_128_ALG_ID for SNOW-3G encryption (not avalaible right now)
* - EIA2_128_ALG_ID for 128 bits AES LTE encryption
* @param[in] stream_cipher All parameters used to compute the decrypted block of data
* @param[out] out The decrypted block of data dynamically allocated
* @return 0 if everything OK, -1 if something failed
*/
int stream_decrypt(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t **out);
int stream_check_integrity(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t *expected);
#undef SECU_DEBUG
#endif /* __UTIL_OSA_OSA_DEFS__H__ */
-175
View File
@@ -1,175 +0,0 @@
/*
* 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
*/
#include "../../../openair3/SECU/kdf.h"
#include <stdint.h>
#include <string.h>
#include "osa_defs.h"
#include "osa_internal.h"
#include "common/utils/LOG/log.h"
/*!
* @brief Derive the keys from key and perform truncate on the generated key to
* reduce his size to 128 bits. Definition of the derivation function can
* be found in 3GPP TS.33401 #A.7
* @param[in] alg_type Algorithm distinguisher
* @param[in] alg_id Algorithm identifier.
* Possible values are:
* - 0 for EIA0 algorithm (Null Integrity Protection algorithm)
* - 1 for 128-EIA1 SNOW 3G
* - 2 for 128-EIA2 AES
* @param[in] key The top key used to derive other subkeys
* @param[out] out Pointer to reference where output of KDF will be stored.
* NOTE: knas is dynamically allocated by the KDF function
*/
int derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t **out)
{
uint8_t string[7] = {0};
/* FC */
string[0] = FC_ALG_KEY_DER;
/* P0 = algorithm type distinguisher */
string[1] = (uint8_t)(alg_type & 0xFF);
/* L0 = length(P0) = 1 */
string[2] = 0x00;
string[3] = 0x01;
/* P1 */
string[4] = alg_id;
/* L1 = length(P1) = 1 */
string[5] = 0x00;
string[6] = 0x01;
#if defined(SECU_DEBUG)
{
int i;
char payload[6 * sizeof(string) + 1];
int index = 0;
for (i = 0; i < sizeof(string); i++)
index += sprintf(&payload[index], "0x%02x ", string[i]);
LOG_D(OSA, "Key deriver input string: %s\n", payload);
}
#endif
byte_array_t data = {.buf = string, .len = 7};
if (*out == NULL) {
*out = malloc(sizeof(uint8_t) * 32);
DevAssert(*out != NULL && "Memory exhausted");
}
kdf(key, data, 32, *out);
return 0;
}
int nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t **out)
{
uint8_t string[7];
/* FC */
string[0] = NR_FC_ALG_KEY_DER;
/* P0 = algorithm type distinguisher */
string[1] = (uint8_t)(alg_type & 0xFF);
/* L0 = length(P0) = 1 */
string[2] = 0x00;
string[3] = 0x01;
/* P1 */
string[4] = alg_id;
/* L1 = length(P1) = 1 */
string[5] = 0x00;
string[6] = 0x01;
byte_array_t data = {.buf = string, .len = 7};
if (*out == NULL) {
*out = malloc(sizeof(uint8_t) * 32);
DevAssert(*out != NULL && "Memory exhausted");
}
kdf(key, data, 32, *out);
// in NR, we use the last 16 bytes, ignoring the first 16 ones
memcpy(*out, *out + 16, 16);
return 0;
}
int nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
{
uint8_t s[10] = {0};
/* FC */
s[0] = NR_FC_ALG_KEY_NG_RAN_STAR_DER;
/* P0 = PCI */
s[1] = (pci & 0x0000ff00) >> 8;
s[2] = (pci & 0x000000ff);
/* L0 = length(P0) = 2 */
s[3] = 0x00;
s[4] = 0x02;
/* P1 = NR ARFCN */
s[5] = (nr_arfcn_dl & 0x00ff0000) >> 16;
s[6] = (nr_arfcn_dl & 0x0000ff00) >> 8;
s[7] = (nr_arfcn_dl & 0x000000ff);
/* L1 = length(P1) = 3 */
s[8] = 0x00;
s[9] = 0x03;
byte_array_t data = {.buf = s, .len = 10};
const uint32_t len_key = 32;
kdf(key, data, len_key, key_ng_ran_star);
return 0;
}
int derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB)
{
uint8_t s[5] = {0};
/* 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;
byte_array_t data = {.buf = s, .len = 5};
kdf(keNB, data, 32, skgNB);
return 0;
}
-344
View File
@@ -1,344 +0,0 @@
/*
* 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
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "osa_rijndael.h"
#include "osa_snow3g.h"
static uint8_t OSA_MULx(uint8_t V, uint8_t c);
static uint8_t OSA_MULxPOW(uint8_t V, uint8_t i, uint8_t c);
static uint32_t OSA_MULalpha(uint8_t c);
static uint32_t OSA_DIValpha(uint8_t c);
static uint32_t OSA_S1(uint32_t w);
static uint32_t OSA_S2(uint32_t w);
static void osa_snow3g_clock_LFSR_initialization_mode(uint32_t F, osa_snow_3g_context_t *s3g_ctx_pP);
static void osa_snow3g_clock_LFSR_key_stream_mode(osa_snow_3g_context_t *snow_3g_context_pP);
static uint32_t osa_snow3g_clock_fsm(osa_snow_3g_context_t *snow_3g_context_pP);
void osa_snow3g_initialize(uint32_t k[4], uint32_t IV[4], osa_snow_3g_context_t *snow_3g_context_pP);
void osa_snow3g_generate_key_stream(uint32_t n, uint32_t *ks, osa_snow_3g_context_t *snow_3g_context_pP);
/* OSA_MULx.
* Input V: an 8-bit input.
* Input c: an 8-bit input.
* Output : an 8-bit input.
* MULx maps 16 bits to 8 bits
*/
static uint8_t OSA_MULx(uint8_t V, uint8_t c)
{
//If the leftmost (i.e. the most significant) bit of V equals 1
if ( V & 0x80 )
return ( (V << 1) ^ c);
else
return ( V << 1);
}
/* OSA_MULxPOW.
* Input V: an 8-bit input.
* Input i: a positive integer.
* Input c: an 8-bit input.
* Output : an 8-bit output.
* MULxPOW maps 16 bits and a positive integer i to 8 bit.
*/
static uint8_t OSA_MULxPOW(uint8_t V, uint8_t i, uint8_t c)
{
if ( i == 0)
return V;
else
return OSA_MULx( OSA_MULxPOW( V, i-1, c ), c);
}
/* The function OSA_MULalpha.
* Input c: 8-bit input.
* Output : 32-bit output.
* maps 8 bits to 32 bits.
*/
static uint32_t OSA_MULalpha(uint8_t c)
{
return ( ( ((uint32_t)OSA_MULxPOW(c,23, 0xa9)) << 24 ) |
( ((uint32_t)OSA_MULxPOW(c, 245, 0xa9)) << 16 ) |
( ((uint32_t)OSA_MULxPOW(c, 48, 0xa9)) << 8 ) |
( ((uint32_t)OSA_MULxPOW(c, 239, 0xa9)) ) ) ;
}
/* The function DIV alpha.
* Input c: 8-bit input.
* Output : 32-bit output.
* maps 8 bits to 32 bit.
*/
static uint32_t OSA_DIValpha(uint8_t c)
{
return ( ( ((uint32_t)OSA_MULxPOW(c, 16, 0xa9)) << 24 ) |
( ((uint32_t)OSA_MULxPOW(c, 39, 0xa9)) << 16 ) |
( ((uint32_t)OSA_MULxPOW(c, 6, 0xa9)) << 8 ) |
( ((uint32_t)OSA_MULxPOW(c, 64, 0xa9)) ) ) ;
}
/* The 32x32-bit S-Box S1
* Input: a 32-bit input.
* Output: a 32-bit output of S1 box.
* The S-Box S1 maps a 32-bit input to a 32-bit output.
* w = w0 || w1 || w2 || w3 the 32-bit input with w0 the most and w3 the least significant byte.
* S1(w)= r0 || r1 || r2 || r3 with r0 the most and r3 the least significant byte.
*/
static uint32_t OSA_S1(uint32_t w)
{
uint8_t r0=0, r1=0, r2=0, r3=0;
uint8_t srw0 = OSA_SR[ (uint8_t)((w >> 24) & 0xff) ];
uint8_t srw1 = OSA_SR[ (uint8_t)((w >> 16) & 0xff) ];
uint8_t srw2 = OSA_SR[ (uint8_t)((w >> 8) & 0xff) ];
uint8_t srw3 = OSA_SR[ (uint8_t)((w) & 0xff) ];
r0 = ( ( OSA_MULx( srw0 , 0x1b) ) ^
( srw1 ) ^
( srw2 ) ^
( (OSA_MULx( srw3, 0x1b)) ^ srw3 )
);
r1 = ( ( ( OSA_MULx( srw0 , 0x1b) ) ^ srw0 ) ^
( OSA_MULx(srw1, 0x1b) ) ^
( srw2 ) ^
( srw3 )
);
r2 = ( ( srw0 ) ^
( ( OSA_MULx( srw1 , 0x1b) ) ^ srw1 ) ^
( OSA_MULx(srw2, 0x1b) ) ^
( srw3 )
);
r3 = ( ( srw0 ) ^
( srw1 ) ^
( ( OSA_MULx( srw2 , 0x1b) ) ^ srw2 ) ^
( OSA_MULx( srw3, 0x1b) )
);
return ( ( ((uint32_t)r0) << 24 ) | ( ((uint32_t)r1) << 16 ) | ( ((uint32_t)r2) << 8 ) | ( ((uint32_t)r3) ) );
}
/* The 32x32-bit S-Box S2
* Input: a 32-bit input.
* Output: a 32-bit output of S2 box.
* The S-Box S2 maps a 32-bit input to a 32-bit output.
* Let w = w0 || w1 || w2 || w3 the 32-bit input with w0 the most and w3 the least significant byte.
* Let S2(w)= r0 || r1 || r2 || r3 with r0 the most and r3 the least significant byte.
*/
static uint32_t OSA_S2(uint32_t w)
{
uint8_t r0=0, r1=0, r2=0, r3=0;
uint8_t sqw0 = OSA_SQ[ (uint8_t)((w >> 24) & 0xff) ];
uint8_t sqw1 = OSA_SQ[ (uint8_t)((w >> 16) & 0xff) ];
uint8_t sqw2 = OSA_SQ[ (uint8_t)((w >> 8) & 0xff) ];
uint8_t sqw3 = OSA_SQ[ (uint8_t)((w) & 0xff) ];
r0 = ( ( OSA_MULx( sqw0 , 0x69) ) ^
( sqw1 ) ^
( sqw2 ) ^
( (OSA_MULx( sqw3, 0x69)) ^ sqw3 )
);
r1 = ( ( ( OSA_MULx( sqw0 , 0x69) ) ^ sqw0 ) ^
( OSA_MULx(sqw1, 0x69) ) ^
( sqw2 ) ^
( sqw3 )
);
r2 = ( ( sqw0 ) ^
( ( OSA_MULx( sqw1 , 0x69) ) ^ sqw1 ) ^
( OSA_MULx(sqw2, 0x69) ) ^
( sqw3 )
);
r3 = ( ( sqw0 ) ^
( sqw1 ) ^
( ( OSA_MULx( sqw2 , 0x69) ) ^ sqw2 ) ^
( OSA_MULx( sqw3, 0x69) )
);
return ( ( ((uint32_t)r0) << 24 ) | ( ((uint32_t)r1) << 16 ) | ( ((uint32_t)r2) << 8 ) | ( ((uint32_t)r3) ) );
}
/* Clocking LFSR in initialization mode.
* LFSR Registers S0 to S15 are updated as the LFSR receives a single clock.
* Input F: a 32-bit word comes from output of FSM.
* See section 3.4.4.
*/
static void osa_snow3g_clock_LFSR_initialization_mode(uint32_t F, osa_snow_3g_context_t *s3g_ctx_pP)
{
uint32_t v = ( ( (s3g_ctx_pP->LFSR_S0 << 8) & 0xffffff00 ) ^
( OSA_MULalpha( (uint8_t)((s3g_ctx_pP->LFSR_S0>>24) & 0xff) ) ) ^
( s3g_ctx_pP->LFSR_S2 ) ^
( (s3g_ctx_pP->LFSR_S11 >> 8) & 0x00ffffff ) ^
( OSA_DIValpha( (uint8_t)( ( s3g_ctx_pP->LFSR_S11) & 0xff ) ) ) ^
( F )
);
s3g_ctx_pP->LFSR_S0 = s3g_ctx_pP->LFSR_S1;
s3g_ctx_pP->LFSR_S1 = s3g_ctx_pP->LFSR_S2;
s3g_ctx_pP->LFSR_S2 = s3g_ctx_pP->LFSR_S3;
s3g_ctx_pP->LFSR_S3 = s3g_ctx_pP->LFSR_S4;
s3g_ctx_pP->LFSR_S4 = s3g_ctx_pP->LFSR_S5;
s3g_ctx_pP->LFSR_S5 = s3g_ctx_pP->LFSR_S6;
s3g_ctx_pP->LFSR_S6 = s3g_ctx_pP->LFSR_S7;
s3g_ctx_pP->LFSR_S7 = s3g_ctx_pP->LFSR_S8;
s3g_ctx_pP->LFSR_S8 = s3g_ctx_pP->LFSR_S9;
s3g_ctx_pP->LFSR_S9 = s3g_ctx_pP->LFSR_S10;
s3g_ctx_pP->LFSR_S10 = s3g_ctx_pP->LFSR_S11;
s3g_ctx_pP->LFSR_S11 = s3g_ctx_pP->LFSR_S12;
s3g_ctx_pP->LFSR_S12 = s3g_ctx_pP->LFSR_S13;
s3g_ctx_pP->LFSR_S13 = s3g_ctx_pP->LFSR_S14;
s3g_ctx_pP->LFSR_S14 = s3g_ctx_pP->LFSR_S15;
s3g_ctx_pP->LFSR_S15 = v;
}
/* Clocking LFSR in keystream mode.
* LFSR Registers S0 to S15 are updated as the LFSR receives a single clock.
* See section 3.4.5.
*/
static void osa_snow3g_clock_LFSR_key_stream_mode(osa_snow_3g_context_t *snow_3g_context_pP)
{
uint32_t v = ( ( (snow_3g_context_pP->LFSR_S0 << 8) & 0xffffff00 ) ^
( OSA_MULalpha( (uint8_t)((snow_3g_context_pP->LFSR_S0>>24) & 0xff) ) ) ^
( snow_3g_context_pP->LFSR_S2 ) ^
( (snow_3g_context_pP->LFSR_S11 >> 8) & 0x00ffffff ) ^
( OSA_DIValpha( (uint8_t)( ( snow_3g_context_pP->LFSR_S11) & 0xff ) ) )
);
snow_3g_context_pP->LFSR_S0 = snow_3g_context_pP->LFSR_S1;
snow_3g_context_pP->LFSR_S1 = snow_3g_context_pP->LFSR_S2;
snow_3g_context_pP->LFSR_S2 = snow_3g_context_pP->LFSR_S3;
snow_3g_context_pP->LFSR_S3 = snow_3g_context_pP->LFSR_S4;
snow_3g_context_pP->LFSR_S4 = snow_3g_context_pP->LFSR_S5;
snow_3g_context_pP->LFSR_S5 = snow_3g_context_pP->LFSR_S6;
snow_3g_context_pP->LFSR_S6 = snow_3g_context_pP->LFSR_S7;
snow_3g_context_pP->LFSR_S7 = snow_3g_context_pP->LFSR_S8;
snow_3g_context_pP->LFSR_S8 = snow_3g_context_pP->LFSR_S9;
snow_3g_context_pP->LFSR_S9 = snow_3g_context_pP->LFSR_S10;
snow_3g_context_pP->LFSR_S10 = snow_3g_context_pP->LFSR_S11;
snow_3g_context_pP->LFSR_S11 = snow_3g_context_pP->LFSR_S12;
snow_3g_context_pP->LFSR_S12 = snow_3g_context_pP->LFSR_S13;
snow_3g_context_pP->LFSR_S13 = snow_3g_context_pP->LFSR_S14;
snow_3g_context_pP->LFSR_S14 = snow_3g_context_pP->LFSR_S15;
snow_3g_context_pP->LFSR_S15 = v;
}
/* Clocking FSM.
* Produces a 32-bit word F.
* Updates FSM registers R1, R2, R3.
* See Section 3.4.6.
*/
static uint32_t osa_snow3g_clock_fsm(osa_snow_3g_context_t *snow_3g_context_pP)
{
uint32_t F = ( ( snow_3g_context_pP->LFSR_S15 + snow_3g_context_pP->FSM_R1 ) & 0xffffffff ) ^ snow_3g_context_pP->FSM_R2 ;
uint32_t r = ( snow_3g_context_pP->FSM_R2 + ( snow_3g_context_pP->FSM_R3 ^ snow_3g_context_pP->LFSR_S5 ) ) & 0xffffffff ;
snow_3g_context_pP->FSM_R3 = OSA_S2(snow_3g_context_pP->FSM_R2);
snow_3g_context_pP->FSM_R2 = OSA_S1(snow_3g_context_pP->FSM_R1);
snow_3g_context_pP->FSM_R1 = r;
return F;
}
/* Initialization.
* Input k[4]: Four 32-bit words making up 128-bit key.
* Input IV[4]: Four 32-bit words making 128-bit initialization variable.
* Output: All the LFSRs and FSM are initialized for key generation.
* See Section 4.1.
*/
void osa_snow3g_initialize(uint32_t k[4], uint32_t IV[4], osa_snow_3g_context_t *snow_3g_context_pP)
{
uint8_t i = 0;
uint32_t F = 0x0;
snow_3g_context_pP->LFSR_S15 = k[3] ^ IV[0];
snow_3g_context_pP->LFSR_S14 = k[2];
snow_3g_context_pP->LFSR_S13 = k[1];
snow_3g_context_pP->LFSR_S12 = k[0] ^ IV[1];
snow_3g_context_pP->LFSR_S11 = k[3] ^ 0xffffffff;
snow_3g_context_pP->LFSR_S10 = k[2] ^ 0xffffffff ^ IV[2];
snow_3g_context_pP->LFSR_S9 = k[1] ^ 0xffffffff ^ IV[3];
snow_3g_context_pP->LFSR_S8 = k[0] ^ 0xffffffff;
snow_3g_context_pP->LFSR_S7 = k[3];
snow_3g_context_pP->LFSR_S6 = k[2];
snow_3g_context_pP->LFSR_S5 = k[1];
snow_3g_context_pP->LFSR_S4 = k[0];
snow_3g_context_pP->LFSR_S3 = k[3] ^ 0xffffffff;
snow_3g_context_pP->LFSR_S2 = k[2] ^ 0xffffffff;
snow_3g_context_pP->LFSR_S1 = k[1] ^ 0xffffffff;
snow_3g_context_pP->LFSR_S0 = k[0] ^ 0xffffffff;
snow_3g_context_pP->FSM_R1 = 0x0;
snow_3g_context_pP->FSM_R2 = 0x0;
snow_3g_context_pP->FSM_R3 = 0x0;
for(i=0; i<32; i++) {
F = osa_snow3g_clock_fsm(snow_3g_context_pP);
osa_snow3g_clock_LFSR_initialization_mode(F, snow_3g_context_pP);
}
}
/* Generation of Keystream.
* input n: number of 32-bit words of keystream.
* input z: space for the generated keystream, assumes
* memory is allocated already.
* output: generated keystream which is filled in z
* See section 4.2.
*/
void osa_snow3g_generate_key_stream(uint32_t n, uint32_t *ks, osa_snow_3g_context_t *snow_3g_context_pP)
{
uint32_t t = 0;
uint32_t F = 0x0;
osa_snow3g_clock_fsm(snow_3g_context_pP); /* Clock FSM once. Discard the output. */
osa_snow3g_clock_LFSR_key_stream_mode(snow_3g_context_pP); /* Clock LFSR in keystream mode once. */
for ( t=0; t<n; t++) {
F = osa_snow3g_clock_fsm(snow_3g_context_pP); /* STEP 1 */
ks[t] = F ^ snow_3g_context_pP->LFSR_S0; /* STEP 2 */
/* Note that ks[t] corresponds to z_{t+1} in section 4.2*/
osa_snow3g_clock_LFSR_key_stream_mode(snow_3g_context_pP); /* STEP 3 */
}
}
-77
View File
@@ -1,77 +0,0 @@
/*
* 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
*/
/*! \file snow3g.h
* \brief
* \author Open source Adapted from Specification of the 3GPP Confidentiality and
* Integrity Algorithms UEA2 & UIA2. Document 2: SNOW 3G Specification
* \integrators Kharbach Othmane, GAUTHIER Lionel.
* \date 2014
* \version
* \note
* \bug
* \warning
*/
#ifndef OSA_SNOW3G_H_
#define OSA_SNOW3G_H_
typedef struct osa_snow_3g_context_s {
uint32_t LFSR_S0;
uint32_t LFSR_S1;
uint32_t LFSR_S2;
uint32_t LFSR_S3;
uint32_t LFSR_S4;
uint32_t LFSR_S5;
uint32_t LFSR_S6;
uint32_t LFSR_S7;
uint32_t LFSR_S8;
uint32_t LFSR_S9;
uint32_t LFSR_S10;
uint32_t LFSR_S11;
uint32_t LFSR_S12;
uint32_t LFSR_S13;
uint32_t LFSR_S14;
uint32_t LFSR_S15;
/* FSM : The Finite State Machine has three 32-bit registers R1, R2 and R3.
*/
uint32_t FSM_R1;
uint32_t FSM_R2;
uint32_t FSM_R3;
} osa_snow_3g_context_t;
/* Initialization.
* Input k[4]: Four 32-bit words making up 128-bit key.
* Input IV[4]: Four 32-bit words making 128-bit initialization variable.
* Output: All the LFSRs and FSM are initialized for key generation.
*/
void osa_snow3g_initialize(uint32_t k[4], uint32_t IV[4], osa_snow_3g_context_t *snow_3g_context_pP);
/* Generation of Keystream.
* input n: number of 32-bit words of keystream.
* input z: space for the generated keystream, assumes
* memory is allocated already.
* output: generated keystream which is filled in z
*/
void osa_snow3g_generate_key_stream(uint32_t n, uint32_t *z, osa_snow_3g_context_t *snow_3g_context_pP);
#endif
-181
View File
@@ -1,181 +0,0 @@
/*
* 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
*/
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "common/utils/LOG/log.h"
#include "byte_array.h"
#include "openair3//SECU//aes_128_ctr.h"
#include "assertions.h"
#include "osa_defs.h"
#include "osa_snow3g.h"
#include "osa_internal.h"
int stream_encrypt_eea0(stream_cipher_t *stream_cipher, uint8_t **out)
{
uint8_t *data = NULL;
uint32_t byte_length;
DevAssert(stream_cipher != NULL);
DevAssert(out != NULL);
LOG_D(OSA,
"Entering stream_encrypt_eea0, bits length %u, bearer %u, "
"count %u, direction %s\n",
stream_cipher->blength,
stream_cipher->bearer,
stream_cipher->count,
stream_cipher->direction == SECU_DIRECTION_DOWNLINK ? "Downlink" : "Uplink");
byte_length = (stream_cipher->blength + 7) >> 3;
if (*out == NULL) {
/* User did not provide output buffer */
data = malloc(byte_length);
*out = data;
} else {
data = *out;
}
memcpy(data, stream_cipher->message, byte_length);
return 0;
}
int stream_encrypt_eea1(stream_cipher_t *stream_cipher, uint8_t **out)
{
osa_snow_3g_context_t snow_3g_context;
int n;
int i = 0;
uint32_t zero_bit = 0;
uint32_t *KS;
uint32_t K[4], IV[4];
DevAssert(stream_cipher != NULL);
DevAssert(stream_cipher->key != NULL);
DevAssert(stream_cipher->key_length == 16);
DevAssert(out != NULL);
n = (stream_cipher->blength + 31) / 32;
zero_bit = stream_cipher->blength & 0x7;
memset(&snow_3g_context, 0, sizeof(snow_3g_context));
/*Initialisation*/
/* Load the confidentiality key for SNOW 3G initialization as in section
3.4. */
memcpy(K + 3, stream_cipher->key + 0, 4); /*K[3] = key[0]; we assume
K[3]=key[0]||key[1]||...||key[31] , with key[0] the
* most important bit of key*/
memcpy(K + 2, stream_cipher->key + 4, 4); /*K[2] = key[1];*/
memcpy(K + 1, stream_cipher->key + 8, 4); /*K[1] = key[2];*/
memcpy(K + 0, stream_cipher->key + 12, 4); /*K[0] = key[3]; we assume
K[0]=key[96]||key[97]||...||key[127] , with key[127] the
* least important bit of key*/
K[3] = hton_int32(K[3]);
K[2] = hton_int32(K[2]);
K[1] = hton_int32(K[1]);
K[0] = hton_int32(K[0]);
/* Prepare the initialization vector (IV) for SNOW 3G initialization as in
section 3.4. */
IV[3] = stream_cipher->count;
IV[2] = ((((uint32_t)stream_cipher->bearer) << 3) | ((((uint32_t)stream_cipher->direction) & 0x1) << 2)) << 24;
IV[1] = IV[3];
IV[0] = IV[2];
/* Run SNOW 3G algorithm to generate sequence of key stream bits KS*/
osa_snow3g_initialize(K, IV, &snow_3g_context);
KS = (uint32_t *)malloc(4 * n);
osa_snow3g_generate_key_stream(n, (uint32_t *)KS, &snow_3g_context);
if (zero_bit > 0) {
KS[n - 1] = KS[n - 1] & (uint32_t)(0xFFFFFFFF << (8 - zero_bit));
}
for (i = 0; i < n; i++) {
KS[i] = hton_int32(KS[i]);
}
/* Exclusive-OR the input data with keystream to generate the output bit
stream */
for (i = 0; i < n * 4; i++) {
stream_cipher->message[i] ^= *(((uint8_t *)KS) + i);
}
if (zero_bit > 0) {
int ceil_index = (stream_cipher->blength + 7) >> 3;
stream_cipher->message[ceil_index - 1] = stream_cipher->message[ceil_index - 1] & (uint8_t)(0xFF << (8 - zero_bit));
}
free(KS);
*out = stream_cipher->message;
return 0;
}
int stream_encrypt_eea2(stream_cipher_t *stream_cipher, uint8_t **out)
{
DevAssert(stream_cipher != NULL);
DevAssert(stream_cipher->key != NULL);
DevAssert(stream_cipher->key_length == 32);
DevAssert(stream_cipher->bearer < 32);
DevAssert(stream_cipher->direction < 2);
DevAssert(stream_cipher->message != NULL);
DevAssert(stream_cipher->blength > 7);
if (*out == NULL) {
*out = calloc(1, (stream_cipher->blength >> 3) + 1);
DevAssert(*out != NULL && "Memory exhausted");
}
aes_128_t p = {0};
memcpy(p.key, stream_cipher->key, stream_cipher->key_length);
p.type = AES_INITIALIZATION_VECTOR_16;
p.iv16.d.count = htonl(stream_cipher->count);
p.iv16.d.bearer = stream_cipher->bearer;
p.iv16.d.direction = stream_cipher->direction;
DevAssert((stream_cipher->blength & 0x07) == 0 && "Cipher length must be multiple of one octet");
const uint32_t byte_lenght = stream_cipher->blength >> 3;
// Precondition: out must have enough space, at least as much as the input
const size_t len_out = byte_lenght;
byte_array_t msg = {.buf = stream_cipher->message, .len =byte_lenght};
aes_128_ctr(&p, msg, len_out, *out);
return 0;
}
int stream_encrypt(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t **out)
{
if (algorithm == EEA0_ALG_ID) {
return stream_encrypt_eea0(stream_cipher, out);
} else if (algorithm == EEA1_128_ALG_ID) {
return stream_encrypt_eea1(stream_cipher, out);
} else if (algorithm == EEA2_128_ALG_ID) {
return stream_encrypt_eea2(stream_cipher, out);
}
LOG_E(OSA, "Provided encryption algorithm is currently not supported = %u\n", algorithm);
return -1;
}
-287
View File
@@ -1,287 +0,0 @@
/*
* 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
*/
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include "assertions.h"
#include "common/utils/LOG/log.h"
#include "openair3/SECU/aes_128_cbc_cmac.h"
#include "osa_defs.h"
#include "osa_snow3g.h"
#include "osa_internal.h"
// see spec 3GPP Confidentiality and Integrity Algorithms UEA2&UIA2. Document 1: UEA2 and UIA2 Specification. Version 1.1
/* OSA_MUL64x.
* Input V: a 64-bit input.
* Input c: a 64-bit input.
* Output : a 64-bit output.
* A 64-bit memory is allocated which is to be freed by the calling
* function.
* See section 4.3.2 for details.
*/
uint64_t OSA_MUL64x(uint64_t V, uint64_t c)
{
if (V & 0x8000000000000000)
return (V << 1) ^ c;
else
return V << 1;
}
/* OSA_MUL64xPOW.
* Input V: a 64-bit input.
* Input i: a positive integer.
* Input c: a 64-bit input.
* Output : a 64-bit output.
* A 64-bit memory is allocated which is to be freed by the calling
function.
* See section 4.3.3 for details.
*/
uint64_t OSA_MUL64xPOW(uint64_t V, uint32_t i, uint64_t c)
{
if (i == 0)
return V;
else
return OSA_MUL64x(OSA_MUL64xPOW(V, i - 1, c), c);
}
/* OSA_MUL64.
* Input V: a 64-bit input.
* Input P: a 64-bit input.
* Input c: a 64-bit input.
* Output : a 64-bit output.
* A 64-bit memory is allocated which is to be freed by the calling
* function.
* See section 4.3.4 for details.
*/
uint64_t OSA_MUL64(uint64_t V, uint64_t P, uint64_t c)
{
uint64_t result = 0;
int i = 0;
for (i = 0; i < 64; i++) {
if ((P >> i) & 0x1)
result ^= OSA_MUL64xPOW(V, i, c);
}
return result;
}
/* osa_mask32bit.
* Input n: an integer in 1-32.
* Output : a 32 bit mask.
* Prepares a 32 bit mask with required number of 1 bits on the MSB side.
*/
uint32_t osa_mask32bit(int n)
{
uint32_t mask = 0x0;
if (n % 32 == 0)
return 0xffffffff;
while (n--)
mask = (mask >> 1) ^ 0x80000000;
return mask;
}
/*!
* @brief Create integrity cmac t for a given message.
* @param[in] stream_cipher Structure containing various variables to setup encoding
* @param[out] out For EIA2 the output string is 32 bits long
*/
int stream_compute_integrity_eia1(stream_cipher_t *stream_cipher, uint8_t out[4])
{
osa_snow_3g_context_t snow_3g_context;
uint32_t K[4], IV[4], z[5];
int i = 0, D;
uint32_t MAC_I = 0;
uint64_t EVAL;
uint64_t V;
uint64_t P;
uint64_t Q;
uint64_t c;
uint64_t M_D_2;
int rem_bits;
uint32_t mask = 0;
uint32_t *message;
message = (uint32_t *)stream_cipher->message; /* To operate 32 bit message internally. */
/* Load the Integrity Key for SNOW3G initialization as in section 4.4. */
memcpy(K + 3, stream_cipher->key + 0, 4); /*K[3] = key[0]; we assume
K[3]=key[0]||key[1]||...||key[31] , with key[0] the
* most important bit of key*/
memcpy(K + 2, stream_cipher->key + 4, 4); /*K[2] = key[1];*/
memcpy(K + 1, stream_cipher->key + 8, 4); /*K[1] = key[2];*/
memcpy(K + 0, stream_cipher->key + 12, 4); /*K[0] = key[3]; we assume
K[0]=key[96]||key[97]||...||key[127] , with key[127] the
* least important bit of key*/
K[3] = hton_int32(K[3]);
K[2] = hton_int32(K[2]);
K[1] = hton_int32(K[1]);
K[0] = hton_int32(K[0]);
/* Prepare the Initialization Vector (IV) for SNOW3G initialization as in
section 4.4. */
IV[3] = (uint32_t)stream_cipher->count;
IV[2] = ((((uint32_t)stream_cipher->bearer) & 0x0000001F) << 27);
IV[1] = (uint32_t)(stream_cipher->count) ^ ((uint32_t)(stream_cipher->direction) << 31);
IV[0] = ((((uint32_t)stream_cipher->bearer) & 0x0000001F) << 27) ^ ((uint32_t)(stream_cipher->direction & 0x00000001) << 15);
// printf ("K:\n");
// hexprint(K, 16);
// printf ("K[0]:%08X\n",K[0]);
// printf ("K[1]:%08X\n",K[1]);
// printf ("K[2]:%08X\n",K[2]);
// printf ("K[3]:%08X\n",K[3]);
// printf ("IV:\n");
// hexprint(IV, 16);
// printf ("IV[0]:%08X\n",IV[0]);
// printf ("IV[1]:%08X\n",IV[1]);
// printf ("IV[2]:%08X\n",IV[2]);
// printf ("IV[3]:%08X\n",IV[3]);
z[0] = z[1] = z[2] = z[3] = z[4] = 0;
/* Run SNOW 3G to produce 5 keystream words z_1, z_2, z_3, z_4 and z_5. */
osa_snow3g_initialize(K, IV, &snow_3g_context);
osa_snow3g_generate_key_stream(5, z, &snow_3g_context);
// printf ("z[0]:%08X\n",z[0]);
// printf ("z[1]:%08X\n",z[1]);
// printf ("z[2]:%08X\n",z[2]);
// printf ("z[3]:%08X\n",z[3]);
// printf ("z[4]:%08X\n",z[4]);
P = ((uint64_t)z[0] << 32) | (uint64_t)z[1];
Q = ((uint64_t)z[2] << 32) | (uint64_t)z[3];
// printf ("P:%16lX\n",P);
// printf ("Q:%16lX\n",Q);
/* Calculation */
D = ceil(stream_cipher->blength / 64.0) + 1;
// printf ("D:%d\n",D);
EVAL = 0;
c = 0x1b;
/* for 0 <= i <= D-3 */
for (i = 0; i < D - 2; i++) {
V = EVAL ^ ((uint64_t)hton_int32(message[2 * i]) << 32 | (uint64_t)hton_int32(message[2 * i + 1]));
EVAL = OSA_MUL64(V, P, c);
// printf ("Mi: %16X %16X\tEVAL: %16lX\n",hton_int32(message[2*i]),hton_int32(message[2*i+1]), EVAL);
}
/* for D-2 */
rem_bits = stream_cipher->blength % 64;
if (rem_bits == 0)
rem_bits = 64;
mask = osa_mask32bit(rem_bits % 32);
if (rem_bits > 32) {
M_D_2 = ((uint64_t)hton_int32(message[2 * (D - 2)]) << 32) | (uint64_t)(hton_int32(message[2 * (D - 2) + 1]) & mask);
} else {
M_D_2 = ((uint64_t)hton_int32(message[2 * (D - 2)]) & mask) << 32;
}
V = EVAL ^ M_D_2;
EVAL = OSA_MUL64(V, P, c);
/* for D-1 */
EVAL ^= stream_cipher->blength;
/* Multiply by Q */
EVAL = OSA_MUL64(EVAL, Q, c);
MAC_I = (uint32_t)(EVAL >> 32) ^ z[4];
// printf ("MAC_I:%16X\n",MAC_I);
MAC_I = hton_int32(MAC_I);
memcpy(out, &MAC_I, 4);
return 0;
}
int stream_compute_integrity_eia2(stream_cipher_t *stream_cipher, uint8_t out[4])
{
DevAssert(stream_cipher != NULL);
;
DevAssert((stream_cipher->blength & 0x7) == 0);
DevAssert(stream_cipher->key_length == 16 && "k_iv.key and stream_cipher mismatch");
DevAssert(stream_cipher->bearer < 32);
DevAssert(stream_cipher->direction < 2);
aes_128_t k_iv = {0};
memcpy(k_iv.key, stream_cipher->key, sizeof(k_iv.key));
k_iv.type = AES_INITIALIZATION_VECTOR_8;
k_iv.iv8.d.bearer = stream_cipher->bearer;
k_iv.iv8.d.direction = stream_cipher->direction;
k_iv.iv8.d.count = htonl(stream_cipher->count);
const size_t m_length = stream_cipher->blength >> 3;
uint8_t result[16] = {0};
byte_array_t msg = {.len = m_length, .buf = stream_cipher->message };
aes_128_cbc_cmac(&k_iv, msg, sizeof(result), result);
memcpy(out, result, 4);
return 0;
}
int stream_compute_integrity(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t out[4])
{
if (algorithm == EIA1_128_ALG_ID) {
LOG_D(OSA, "EIA1 algorithm applied for integrity\n");
return stream_compute_integrity_eia1(stream_cipher, out);
} else if (algorithm == EIA2_128_ALG_ID) {
LOG_D(OSA, "EIA2 algorithm applied for integrity\n");
return stream_compute_integrity_eia2(stream_cipher, out);
}
LOG_E(OSA, "Provided integrity algorithm is currently not supported = %u\n", algorithm);
return -1;
}
int stream_check_integrity(uint8_t algorithm, stream_cipher_t *stream_cipher, uint8_t *expected)
{
uint8_t result[4];
if (algorithm != EIA0_ALG_ID) {
if (stream_compute_integrity(algorithm, stream_cipher, result) != 0) {
return -1;
}
if (memcmp(result, expected, 4) != 0) {
LOG_E(OSA,
"Mismatch found in integrity for algorithm %u,\n"
"\tgot %02x.%02x.%02x.%02x, expecting %02x.%02x.%02x.%02x\n",
algorithm,
result[0],
result[1],
result[2],
result[3],
expected[0],
expected[1],
expected[2],
expected[3]);
return -1;
}
}
/* Integrity verification succeeded */
return 0;
}
-2
View File
@@ -23,8 +23,6 @@
#include "commonDef.h"
#include "security_types.h"
#include "queue.h"
#ifndef COMMON_TYPES_H_
-44
View File
@@ -42,14 +42,6 @@
#define AUTN_LENGTH_BITS (128)
#define AUTN_LENGTH_OCTETS (AUTN_LENGTH_BITS/8)
/* Some methods to convert a string to an int64_t */
/*
#define STRING_TO_64BITS(sTRING, cONTAINER) \
sscanf(sTRING, "%" SCN64, cONTAINER)
#define STRING_TO_U64BITS(sTRING, cONTAINER) \
sscanf(sTRING, "%" SCNu64, cONTAINER)
*/
/* Converts a string to 128 bits gmplib integer holder */
# define STRING_TO_XBITS(sTRING, lENGTH, cONTAINER, rET) \
do { \
@@ -63,18 +55,6 @@ STRING_TO_XBITS(sTRING, 16, cONTAINER, rET)
# define STRING_TO_256BITS(sTRING, cONTAINER, rET) \
STRING_TO_XBITS(sTRING, 32, cONTAINER, rET)
# define STRING_TO_RAND STRING_TO_128BITS
# define STRING_TO_AUTH_KEY STRING_TO_128BITS
# define STRING_TO_AUTH_RES STRING_TO_128BITS
# define STRING_TO_AUTN STRING_TO_128BITS
# define STRING_TO_KASME STRING_TO_256BITS
# define STRING_TO_XRES(sTRING, lENGTH, cONTAINER, rET) \
do { \
STRING_TO_XBITS(sTRING, lENGTH, (cONTAINER)->data, rET); \
if (rET != -1) \
(cONTAINER)->size = lENGTH; \
} while(0)
/* RES amd XRES can have a variable length of 4-16 octets */
typedef struct {
uint8_t size;
@@ -107,28 +87,4 @@ typedef struct eutran_vector_s {
uint8_t kasme[KASME_LENGTH_OCTETS];
} eutran_vector_t;
#define FC_KASME (0x10)
#define FC_KENB (0x11)
#define FC_NH (0x12)
#define FC_KENB_STAR (0x13)
/* 33401 #A.7 Algorithm for key derivation function.
* This FC should be used for:
* - NAS Encryption algorithm
* - NAS Integrity algorithm
* - RRC Encryption algorithm
* - RRC Integrity algorithm
* - User Plane Encryption algorithm
*/
#define FC_ALG_KEY_DER (0x15)
#define FC_KASME_TO_CK (0x16)
typedef enum {
NAS_ENC_ALG = 0x01,
NAS_INT_ALG = 0x02,
RRC_ENC_ALG = 0x03,
RRC_INT_ALG = 0x04,
UP_ENC_ALG = 0x05,
UP_INT_ALG = 0x06
} algorithm_type_dist_t;
#endif /* SECURITY_TYPES_H_ */
+8 -13
View File
@@ -53,8 +53,6 @@ Description Defines the layer 3 messages supported by the NAS sublayer
#include "secu_defs.h"
#include "emmData.h"
//#define DEBUG_NAS_MESSAGE
/****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/
/****************************************************************************/
@@ -1019,7 +1017,8 @@ static int _nas_message_decrypt(
stream_cipher.message = (unsigned char *)src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea1(&stream_cipher, (unsigned char *)dest);
stream_compute_encrypt(EEA1_128_ALG_ID, &stream_cipher, (unsigned char *)dest);
/* Decode the first octet (security header type or EPS bearer identity,
* and protocol discriminator) */
DECODE_U8(dest, *(uint8_t*)(&header), size);
@@ -1054,7 +1053,8 @@ static int _nas_message_decrypt(
stream_cipher.message = (unsigned char *)src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea1(&stream_cipher, (unsigned char *)dest);
stream_compute_encrypt(EEA1_128_ALG_ID, &stream_cipher, (unsigned char *)dest);
/* Decode the first octet (security header type or EPS bearer identity,
* and protocol discriminator) */
DECODE_U8(dest, *(uint8_t*)(&header), size);
@@ -1186,8 +1186,7 @@ static int _nas_message_encrypt(
stream_cipher.message = (unsigned char *)src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea1(&stream_cipher, (unsigned char *)dest);
stream_compute_encrypt(EEA1_128_ALG_ID, &stream_cipher, (unsigned char *)dest);
LOG_FUNC_RETURN (length);
}
@@ -1217,7 +1216,7 @@ static int _nas_message_encrypt(
stream_cipher.message = (unsigned char *)src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea2(&stream_cipher, (unsigned char *)dest);
stream_compute_encrypt(EEA2_128_ALG_ID, &stream_cipher, (unsigned char *)dest);
LOG_FUNC_RETURN (length);
@@ -1356,10 +1355,8 @@ static uint32_t _nas_message_get_mac(
stream_cipher.message = (unsigned char *)buffer;
/* length in bits */
stream_cipher.blength = length << 3;
stream_compute_integrity(EIA1_128_ALG_ID, &stream_cipher, mac);
nas_stream_encrypt_eia1(
&stream_cipher,
mac);
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EIA1 returned MAC %x.%x.%x.%x(%u) for length %d direction %d, count %d",
mac[0], mac[1], mac[2],mac[3],
@@ -1402,10 +1399,8 @@ static uint32_t _nas_message_get_mac(
stream_cipher.message = (unsigned char *)buffer;
/* length in bits */
stream_cipher.blength = length << 3;
stream_compute_integrity(EIA2_128_ALG_ID, &stream_cipher, mac);
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EIA2 returned MAC %x.%x.%x.%x(%u) for length %d direction %d, count %d",
mac[0], mac[1], mac[2],mac[3],
+61 -36
View File
@@ -29,10 +29,11 @@
#ifndef MILENAGE_H
#define MILENAGE_H
#include <openssl/aes.h>
#include "openair3/SECU/aes_128_ecb.h"
#define u8 uint8_t
/**
milenage_f1 - Milenage f1 and f1* algorithms
@opc: OPc = 128-bit value derived from OP and K
@@ -45,16 +46,29 @@
Returns: true on success, false on failure
*/
void aes_128_encrypt_block(const u8* key, const u8* in, u8* out) {
AES_KEY k;
u8 tmp[16];
AES_set_encrypt_key(key, 128, &k);
AES_encrypt(in, tmp, &k);
void aes_128_encrypt_block(const uint8_t *key, const uint8_t *in, uint8_t *out)
{
abort();
assert(0 != 0 && "Here we are!");
// Precondition: key, in and out occupy 16 bytes
aes_128_t k_iv = {.type = NONE_INITIALIZATION_VECTOR};
memcpy(k_iv.key, key, sizeof(k_iv.key));
byte_array_t msg = {.buf = (uint8_t *)in, .len = 16};
uint8_t tmp[16] = {0};
aes_128_ecb(&k_iv, msg, sizeof(tmp), tmp);
memcpy(out, tmp, sizeof(tmp));
}
static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s) {
u8 tmp1[16], tmp2[16], tmp3[16];
static bool milenage_f1(const uint8_t *opc,
const uint8_t *k,
const uint8_t *_rand,
const uint8_t *sqn,
const uint8_t *amf,
uint8_t *mac_a,
uint8_t *mac_s)
{
uint8_t tmp1[16], tmp2[16], tmp3[16];
int i;
/* tmp1 = TEMP = E_K(RAND XOR OP_C) */
@@ -62,10 +76,10 @@ static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
tmp1[i] = _rand[i] ^ opc[i];
aes_128_encrypt_block(k, tmp1, tmp1);
AES_KEY kTab;
uint8_t cyphered[16];
AES_set_encrypt_key(k, 128, &kTab);
AES_encrypt(tmp1, cyphered, &kTab);
uint8_t cyphered[16] = {0};
aes_128_encrypt_block(k, tmp1, cyphered);
/* tmp2 = IN1 = SQN || AMF || SQN || AMF */
memcpy(tmp2, sqn, 6);
memcpy(tmp2 + 6, amf, 2);
@@ -97,7 +111,6 @@ static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
return true;
}
/**
milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms
@opc: OPc = 128-bit value derived from OP and K
@@ -110,9 +123,16 @@ static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
@akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL
Returns: true on success, false on failure
*/
static bool milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar) {
u8 tmp1[16], tmp2[16], tmp3[16];
static bool milenage_f2345(const uint8_t *opc,
const uint8_t *k,
const uint8_t *_rand,
uint8_t *res,
uint8_t *ck,
uint8_t *ik,
uint8_t *ak,
uint8_t *akstar)
{
uint8_t tmp1[16], tmp2[16], tmp3[16];
int i;
/* tmp2 = TEMP = E_K(RAND XOR OP_C) */
@@ -186,7 +206,6 @@ static bool milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
return true;
}
/**
milenage_generate - Generate AKA AUTN,IK,CK,RES
@opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
@@ -200,11 +219,18 @@ static bool milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
@res: Buffer for RES = 64-bit signed response (f2), or %NULL
@res_len: Max length for res; set to used length or 0 on failure
*/
static bool milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik,
u8 *ck, u8 *res) {
static bool milenage_generate(const uint8_t *opc,
const uint8_t *amf,
const uint8_t *k,
const uint8_t *sqn,
const uint8_t *_rand,
uint8_t *autn,
uint8_t *ik,
uint8_t *ck,
uint8_t *res)
{
int i;
u8 mac_a[8], ak[6];
uint8_t mac_a[8], ak[6];
if (!milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) ||
!milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
@@ -219,7 +245,6 @@ static bool milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
return true;
}
/**
milenage_auts - Milenage AUTS validation
@opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
@@ -232,10 +257,10 @@ static bool milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
#define p(a) printf("%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", (int)((a)[0]), (int)((a)[1]), (int)((a)[2]), (int)((a)[3]),(int)((a)[4]), (int)((a)[5]));
// valid code but put in comment as it is not used right now
#if 0
static bool milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts,
u8 *sqn) {
u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
u8 ak[6], mac_s[8];
static bool milenage_auts(const uint8_t *opc, const uint8_t *k, const uint8_t *_rand, const uint8_t *auts,
uint8_t *sqn) {
uint8_t amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
uint8_t ak[6], mac_s[8];
int i;
if (!milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
@@ -262,8 +287,8 @@ static bool milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8
@kc: Buffer for Kc = 64-bit Kc
Returns: 0 on success, -1 on failure
*/
static bool gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc) {
u8 res[8], ck[16], ik[16];
static bool gsm_milenage(const uint8_t *opc, const uint8_t *k, const uint8_t *_rand, uint8_t *sres, uint8_t *kc) {
uint8_t res[8], ck[16], ik[16];
int i;
if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL))
@@ -298,12 +323,12 @@ static bool gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres,
@auts: 112-bit buffer for AUTS
Returns: 0 on success, -1 on failure, or -2 on synchronization failure
*/
static int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
u8 *auts) {
static int milenage_check(const uint8_t *opc, const uint8_t *k, const uint8_t *sqn, const uint8_t *_rand,
const uint8_t *autn, uint8_t *ik, uint8_t *ck, uint8_t *res, size_t *res_len,
uint8_t *auts) {
int i;
u8 mac_a[8], ak[6], rx_sqn[6];
const u8 *amf;
uint8_t mac_a[8], ak[6], rx_sqn[6];
const uint8_t *amf;
if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
return -1;
@@ -315,7 +340,7 @@ static int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_
rx_sqn[i] = autn[i] ^ ak[i];
if (memcmp(rx_sqn, sqn, 6) <= 0) {
u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
uint8_t auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
return -1;
@@ -342,7 +367,7 @@ static int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_
return 0;
}
static void milenage_opc_gen(const u8 *k, const u8 *op, u8 *opc) {
static void milenage_opc_gen(const uint8_t *k, const uint8_t *op, uint8_t *opc) {
int i;
/* Encrypt OP using K */
aes_128_encrypt_block(k, op, opc);
+5 -9
View File
@@ -40,6 +40,7 @@
#include "aka_functions.h"
#include "secu_defs.h"
#include "kdf.h"
#include "key_nas_deriver.h"
#include "PduSessionEstablishRequest.h"
#include "PduSessionEstablishmentAccept.h"
#include "RegistrationAccept.h"
@@ -50,6 +51,7 @@
#include <openair1/PHY/phy_extern_nr_ue.h>
#include <openair1/SIMULATION/ETH_TRANSPORT/proto.h>
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
#include "openair3/SECU/nas_stream_eia2.h"
uint8_t *registration_request_buf;
uint32_t registration_request_len;
@@ -597,9 +599,7 @@ static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initia
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
stream_compute_integrity(EIA2_128_ALG_ID, &stream_cipher, mac);
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
@@ -702,9 +702,7 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas, as_nas_info_t *initia
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
stream_compute_integrity(EIA2_128_ALG_ID, &stream_cipher, mac);
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
@@ -861,9 +859,7 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
stream_compute_integrity(EIA2_128_ALG_ID, &stream_cipher, mac);
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
+2 -1
View File
@@ -62,9 +62,10 @@ typedef struct{
};
} iv8_t;
typedef enum{
typedef enum {
AES_INITIALIZATION_VECTOR_8,
AES_INITIALIZATION_VECTOR_16,
NONE_INITIALIZATION_VECTOR,
AES_INITIALIZATION_VECTOR_END,
} iv_e;
+53
View File
@@ -0,0 +1,53 @@
/*
* 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
*/
#include "aes_128_ecb.h"
#include "common/utils/assertions.h"
#include <openssl/aes.h>
#include <openssl/err.h>
#include <openssl/evp.h>
void aes_128_ecb(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out])
{
DevAssert(k_iv != NULL);
DevAssert(k_iv->type == NONE_INITIALIZATION_VECTOR);
// Create and initialise the context
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
DevAssert(ctx != NULL);
// Initialise the encryption operation.
int rc = EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, k_iv->key, NULL);
DevAssert(rc == 1);
int len_ev = 0;
rc = EVP_EncryptUpdate(ctx, out, &len_ev, msg.buf, msg.len);
DevAssert(!(len_ev > len_out) && "Buffer overflow");
// Finalise the encryption. Normally ciphertext bytes may be written at
// this stage, but this does not occur in GCM mode
rc = EVP_EncryptFinal_ex(ctx, out + len_ev, &len_ev);
DevAssert(rc == 1);
// Get the tag
// rc == EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
EVP_CIPHER_CTX_free(ctx);
}
+30
View File
@@ -0,0 +1,30 @@
/*
* 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 AES_128_ECB_OAI_H
#define AES_128_ECB_OAI_H
#include "aes_128.h"
#include "common/utils/ds/byte_array.h"
void aes_128_ecb(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out]);
#endif
+202 -40
View File
@@ -19,16 +19,84 @@
* contact@openairinterface.org
*/
#include "aes_128.h"
#include "aes_128_cbc_cmac.h"
#include "common/utils/assertions.h"
#include "common/utils/LOG/log.h"
#include "kdf.h"
#include "key_nas_deriver.h"
#include "nas_stream_eea1.h"
#include "nas_stream_eea2.h"
#include "nas_stream_eia1.h"
#include "nas_stream_eia2.h"
#include "secu_defs.h"
#include "snow3g.h"
#include <arpa/inet.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "security_types.h"
#include "secu_defs.h"
#include "kdf.h"
#define FC_KENB (0x11)
#define FC_NH (0x12)
#define FC_KENB_STAR (0x13)
/* 33401 #A.7 Algorithm for key derivation function.
* This FC should be used for:
* - NAS Encryption algorithm
* - NAS Integrity algorithm
* - RRC Encryption algorithm
* - RRC Integrity algorithm
* - User Plane Encryption algorithm
*/
#define FC_ALG_KEY_DER (0x15)
#define FC_KASME_TO_CK (0x16)
#define NR_FC_ALG_KEY_DER (0x69)
#define NR_FC_ALG_KEY_NG_RAN_STAR_DER (0x70)
// #define SECU_DEBUG 1
static void derive_key_common(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t kasme[32], uint8_t FC, uint8_t out[32])
{
uint8_t s[7];
#if defined(SECU_DEBUG)
int i;
#endif
/* FC */
s[0] = FC;
/* P0 = algorithm type distinguisher */
s[1] = (uint8_t)(alg_type & 0xFF);
/* L0 = length(P0) = 1 */
s[2] = 0x00;
s[3] = 0x01;
/* P1 */
s[4] = alg_id;
/* L1 = length(P1) = 1 */
s[5] = 0x00;
s[6] = 0x01;
#if defined(SECU_DEBUG)
printf("%s FC %d nas_alg_type distinguisher %d nas_enc_alg_identity %d\n", __FUNCTION__, FC_ALG_KEY_DER, alg_type, alg_id);
for (i = 0; i < 7; i ++) {
printf("0x%02x ", s[i]);
}
printf("\n");
#endif
byte_array_t data = {.len = 7, .buf = s};
kdf(kasme, data, 32, out);
}
#define SECU_DEBUG 1
/*!
* @brief Derive the kNASenc from kasme and perform truncate on the generated key to
* reduce his size to 128 bits. Definition of the derivation function can
@@ -41,50 +109,144 @@
* - 2 for 128-EIA2 AES
* @param[in] kasme Key for MME as provided by AUC
* @param[out] knas Pointer to reference where output of KDF will be stored.
*/
void derive_key_nas(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t kasme[32], uint8_t knas[32])
{
derive_key_common(alg_type, alg_id, kasme, FC_ALG_KEY_DER, knas);
}
void nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16])
{
uint8_t tmp[32] = {0};
derive_key_common(alg_type, alg_id, key, NR_FC_ALG_KEY_DER, tmp);
// Only the last 16 bytes are needed in 5G
memcpy(out, &tmp[16], 16);
}
/*!
* @brief Derive the keys from key and perform truncate on the generated key to
* reduce his size to 128 bits. Definition of the derivation function can
* be found in 3GPP TS.33401 #A.7
* @param[in] alg_type Algorithm distinguisher
* @param[in] alg_id Algorithm identifier.
* Possible values are:
* - 0 for EIA0 algorithm (Null Integrity Protection algorithm)
* - 1 for 128-EIA1 SNOW 3G
* - 2 for 128-EIA2 AES
* @param[in] key The top key used to derive other subkeys
* @param[out] out Pointer to reference where output of KDF will be stored.
* NOTE: knas is dynamically allocated by the KDF function
*/
int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
const uint8_t kasme[32], uint8_t *knas)
#ifndef NAS_UE
void derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB)
{
uint8_t s[7];
uint8_t out[32];
#if defined(SECU_DEBUG)
int i;
uint8_t s[7] = {0};
// FC
s[0] = FC_KENB;
// P0 = Uplink NAS count
s[1] = (nas_count & 0xff000000) >> 24;
s[2] = (nas_count & 0x00ff0000) >> 16;
s[3] = (nas_count & 0x0000ff00) >> 8;
s[4] = (nas_count & 0x000000ff);
// Length of NAS count
s[5] = 0x00;
s[6] = 0x04;
byte_array_t data = {.buf = s, .len = 7};
kdf(kasme, data, 32, keNB);
}
#endif
/* FC */
s[0] = FC_ALG_KEY_DER;
/* P0 = algorithm type distinguisher */
s[1] = (uint8_t)(nas_alg_type & 0xFF);
/* L0 = length(P0) = 1 */
s[2] = 0x00;
s[3] = 0x01;
/* P1 */
s[4] = nas_enc_alg_id;
/* L1 = length(P1) = 1 */
s[5] = 0x00;
s[6] = 0x01;
#if defined(SECU_DEBUG)
printf("%s FC %d nas_alg_type distinguisher %d nas_enc_alg_identity %d\n",
__FUNCTION__, FC_ALG_KEY_DER, nas_alg_type, nas_enc_alg_id);
for (i = 0; i < 7; i ++) {
printf("0x%02x ", s[i]);
void derive_keNB_star(const uint8_t *kenb_32,
const uint16_t pci,
const uint32_t earfcn_dl,
const bool is_rel8_only,
uint8_t *kenb_star)
{
// see 33.401 section A.5 KeNB* derivation function
uint8_t s[10] = {0};
byte_array_t data = {.buf = s};
// FC = 0x13
s[0] = FC_KENB_STAR;
// P0 = PCI (target physical cell id)
s[1] = (pci & 0x0000ff00) >> 8;
s[2] = (pci & 0x000000ff);
// L0 = length of PCI (i.e. 0x00 0x02)
s[3] = 0x00;
s[4] = 0x02;
// P1 = EARFCN-DL (target physical cell downlink frequency)
if (is_rel8_only) {
s[5] = (earfcn_dl & 0x0000ff00) >> 8;
s[6] = (earfcn_dl & 0x000000ff);
s[7] = 0x00;
s[8] = 0x02;
data.len = 9;
} else {
s[5] = (earfcn_dl & 0x00ff0000) >> 16;
s[6] = (earfcn_dl & 0x0000ff00) >> 8;
s[7] = (earfcn_dl & 0x000000ff);
s[8] = 0x00;
s[9] = 0x03;
data.len = 10;
}
printf("\n");
#endif
kdf(kenb_32, data, 32, kenb_star);
//kdf(kasme, 32, s, 7, out, 32);
byte_array_t data = {.len = 7, .buf = s};
kdf(kasme, data, 32, out);
// L1 length of EARFCN-DL (i.e. L1 = 0x00 0x02 if EARFCN-DL is between 0 and 65535, and L1 = 0x00 0x03 if EARFCN-DL is between
// 65536 and 262143) NOTE: The length of EARFCN-DL cannot be generally set to 3 bytes for backward compatibility reasons: A Rel-8
// entity (UE or eNB) would always assume an input parameter length of 2 bytes for the EARFCN-DL. This
// would lead to different derived keys if another entity assumed an input parameter length of 3 bytes for the
// EARFCN-DL.
}
memcpy(knas, &out[31-16+1], 16);
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
{
uint8_t s[10] = {0};
return 0;
/* FC */
s[0] = NR_FC_ALG_KEY_NG_RAN_STAR_DER;
/* P0 = PCI */
s[1] = (pci & 0x0000ff00) >> 8;
s[2] = (pci & 0x000000ff);
/* L0 = length(P0) = 2 */
s[3] = 0x00;
s[4] = 0x02;
/* P1 = NR ARFCN */
s[5] = (nr_arfcn_dl & 0x00ff0000) >> 16;
s[6] = (nr_arfcn_dl & 0x0000ff00) >> 8;
s[7] = (nr_arfcn_dl & 0x000000ff);
/* L1 = length(P1) = 3 */
s[8] = 0x00;
s[9] = 0x03;
byte_array_t data = {.buf = s, .len = 10};
const uint32_t len_key = 32;
kdf(key, data, len_key, key_ng_ran_star);
}
void derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB)
{
uint8_t s[5] = {0};
/* 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;
byte_array_t data = {.buf = s, .len = 5};
kdf(keNB, data, 32, skgNB);
}
+33
View File
@@ -0,0 +1,33 @@
#ifndef KEY_NAS_DERIVER_H
#define KEY_NAS_DERIVER_H
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
typedef enum {
NAS_ENC_ALG = 0x01,
NAS_INT_ALG = 0x02,
RRC_ENC_ALG = 0x03,
RRC_INT_ALG = 0x04,
UP_ENC_ALG = 0x05,
UP_INT_ALG = 0x06
} algorithm_type_dist_t;
void derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB);
void derive_keNB_star(const uint8_t *kenb_32,
const uint16_t pci,
const uint32_t earfcn_dl,
const bool is_rel8_only,
uint8_t *kenb_star);
void derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id, const uint8_t kasme[32], uint8_t knas[32]);
void derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB);
void nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16]);
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star);
#endif
+44
View File
@@ -0,0 +1,44 @@
/*
* 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
*/
#include "nas_stream_eea0.h"
#include "common/utils/assertions.h"
#include "common/utils/LOG/log.h"
#include <string.h>
void nas_stream_encrypt_eea0(nas_stream_cipher_t const *stream_cipher, uint8_t *out)
{
DevAssert(stream_cipher != NULL);
DevAssert(out != NULL);
LOG_D(OSA,
"Entering stream_encrypt_eea0, bits length %u, bearer %u, "
"count %u, direction %s\n",
stream_cipher->blength,
stream_cipher->bearer,
stream_cipher->count,
stream_cipher->direction == SECU_DIRECTION_DOWNLINK ? "Downlink" : "Uplink");
uint32_t byte_length = (stream_cipher->blength + 7) >> 3;
memcpy(out, stream_cipher->message, byte_length);
}
@@ -19,32 +19,14 @@
* contact@openairinterface.org
*/
#ifndef OSA_INTERNAL_H_
#define OSA_INTERNAL_H_
#ifndef OAI_NAS_STREAM_EEA0_H
#define OAI_NAS_STREAM_EEA0_H
#define FC_KENB (0x11)
#define FC_NH (0x12)
#define FC_KENB_STAR (0x13)
/* 33401 #A.7 Algorithm for key derivation function.
* This FC should be used for:
* - NAS Encryption algorithm
* - NAS Integrity algorithm
* - RRC Encryption algorithm
* - RRC Integrity algorithm
* - User Plane Encryption algorithm
*/
#define FC_ALG_KEY_DER (0x15)
#define FC_KASME_TO_CK (0x16)
#include "secu_defs.h"
#define NR_FC_ALG_KEY_DER (0x69)
#define NR_FC_ALG_KEY_NG_RAN_STAR_DER (0x70)
#include <stdlib.h>
#include <stdint.h>
void nas_stream_encrypt_eea0(nas_stream_cipher_t const *stream_cipher, uint8_t *out);
#ifndef hton_int32
# define hton_int32(x) \
(((x & 0x000000FF) << 24) | ((x & 0x0000FF00) << 8) | \
((x & 0x00FF0000) >> 8) | ((x & 0xFF000000) >> 24))
#endif
// #define SECU_DEBUG
#endif /* OSA_INTERNAL_H_ */
+2 -7
View File
@@ -26,13 +26,10 @@
#include "assertions.h"
#include "conversions.h"
#include "secu_defs.h"
#include "nas_stream_eea1.h"
#include "snow3g.h"
// #define SECU_DEBUG
int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t *out)
void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t *out)
{
snow_3g_context_t snow_3g_context;
int n ;
@@ -106,6 +103,4 @@ int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t *out)
if (zero_bit > 0) {
out[ceil_index - 1] = stream_cipher->message[ceil_index - 1];
}
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
/*
* 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 OAI_NAS_STREAM_EEA1_H
#define OAI_NAS_STREAM_EEA1_H
#include "secu_defs.h"
#include <stdlib.h>
#include <stdint.h>
void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t *out);
#endif
+2 -4
View File
@@ -28,9 +28,9 @@
#include "aes_128_ctr.h"
#include "assertions.h"
#include "conversions.h"
#include "secu_defs.h"
#include "nas_stream_eea2.h"
int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t *out)
void nas_stream_encrypt_eea2(nas_stream_cipher_t const *stream_cipher, uint8_t *out)
{
DevAssert(stream_cipher != NULL);
DevAssert(stream_cipher->key != NULL);
@@ -53,6 +53,4 @@ int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t *out)
const size_t len_out = byte_lenght;
byte_array_t msg = {.buf = stream_cipher->message, .len = byte_lenght};
aes_128_ctr(&p, msg, len_out, out);
return 0;
}
@@ -1,3 +1,4 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -19,7 +20,12 @@
* contact@openairinterface.org
*/
#ifndef OAI_NAS_STREAM_EEA2_H
#define OAI_NAS_STREAM_EEA2_H
#include "secu_defs.h"
#include <stdint.h>
/* Rijndael S-box OSA_SR */
static const uint8_t OSA_SR[256] = {
@@ -53,3 +59,7 @@ static const uint8_t OSA_SQ[256] = {
0x04, 0xC8, 0x9D, 0xE7, 0x14, 0xB1, 0x87, 0x9C, 0xDF, 0x6F, 0xF9, 0xDA, 0x2A, 0xC4, 0x59, 0x16, 0x74, 0x91, 0xAB, 0x26,
0x61, 0x76, 0x34, 0x2B, 0xAD, 0x99, 0xFB, 0x72, 0xEC, 0x33, 0x12, 0xDE, 0x98, 0x3B, 0xC0, 0x9B, 0x3E, 0x18, 0x10, 0x3A,
0x56, 0xE1, 0x77, 0xC9, 0x1E, 0x9E, 0x95, 0xA3, 0x90, 0x19, 0xA8, 0x6C, 0x09, 0xD0, 0xF0, 0x86};
void nas_stream_encrypt_eea2(nas_stream_cipher_t const *stream_cipher, uint8_t *out);
#endif
+6 -13
View File
@@ -25,7 +25,7 @@
#include <string.h>
#include <math.h> // double ceil(double x);
#include "secu_defs.h"
#include "nas_stream_eia1.h"
#include "assertions.h"
#include "conversions.h"
@@ -33,12 +33,6 @@
#define SECU_DEBUG
uint64_t MUL64x(uint64_t V, uint64_t c);
uint64_t MUL64xPOW(uint64_t V, uint32_t i, uint64_t c);
uint64_t MUL64(uint64_t V, uint64_t P, uint64_t c);
int nas_stream_encrypt_eia1(nas_stream_cipher_t *stream_cipher, uint8_t out[4]);
// see spec 3GPP Confidentiality and Integrity Algorithms UEA2&UIA2. Document 1: UEA2 and UIA2 Specification. Version 1.1
/* MUL64x.
@@ -49,7 +43,7 @@ int nas_stream_encrypt_eia1(nas_stream_cipher_t *stream_cipher, uint8_t out
* function.
* See section 4.3.2 for details.
*/
uint64_t MUL64x(uint64_t V, uint64_t c)
static uint64_t MUL64x(uint64_t V, uint64_t c)
{
if ( V & 0x8000000000000000 )
return (V << 1) ^ c;
@@ -65,7 +59,7 @@ uint64_t MUL64x(uint64_t V, uint64_t c)
function.
* See section 4.3.3 for details.
*/
uint64_t MUL64xPOW(uint64_t V, uint32_t i, uint64_t c)
static uint64_t MUL64xPOW(uint64_t V, uint32_t i, uint64_t c)
{
if ( i == 0)
return V;
@@ -81,7 +75,7 @@ uint64_t MUL64xPOW(uint64_t V, uint32_t i, uint64_t c)
* function.
* See section 4.3.4 for details.
*/
uint64_t MUL64(uint64_t V, uint64_t P, uint64_t c)
static uint64_t MUL64(uint64_t V, uint64_t P, uint64_t c)
{
uint64_t result = 0;
int i = 0;
@@ -99,7 +93,7 @@ uint64_t MUL64(uint64_t V, uint64_t P, uint64_t c)
* Output : a 32 bit mask.
* Prepares a 32 bit mask with required number of 1 bits on the MSB side.
*/
uint32_t mask32bit(int n)
static uint32_t mask32bit(int n)
{
uint32_t mask=0x0;
@@ -118,7 +112,7 @@ uint32_t mask32bit(int n)
* @param[in] stream_cipher Structure containing various variables to setup encoding
* @param[out] out For EIA1 the output string is 32 bits long
*/
int nas_stream_encrypt_eia1(nas_stream_cipher_t *stream_cipher, uint8_t out[4])
void nas_stream_encrypt_eia1(nas_stream_cipher_t const *stream_cipher, uint8_t out[4])
{
snow_3g_context_t snow_3g_context;
uint32_t K[4],IV[4], z[5];
@@ -218,5 +212,4 @@ int nas_stream_encrypt_eia1(nas_stream_cipher_t *stream_cipher, uint8_t out[4])
//printf ("MAC_I:%16X\n",MAC_I);
MAC_I = hton_int32(MAC_I);
memcpy(out, &MAC_I, 4);
return 0;
}
+29
View File
@@ -0,0 +1,29 @@
/*
* 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 OAI_NAS_STREAM_EIA1_H
#define OAI_NAS_STREAM_EIA1_H
#include "secu_defs.h"
void nas_stream_encrypt_eia1(nas_stream_cipher_t const* stream_cipher, uint8_t out[4]);
#endif
+3 -4
View File
@@ -25,7 +25,7 @@
#include <stdint.h>
#include <string.h>
#include "secu_defs.h"
#include "nas_stream_eia2.h"
#include <arpa/inet.h>
#include "aes_128_cbc_cmac.h"
@@ -40,7 +40,7 @@
* @param[out] out For EIA2 the output string is 32 bits long
*/
int nas_stream_encrypt_eia2(nas_stream_cipher_t *stream_cipher, uint8_t out[4])
void nas_stream_encrypt_eia2(nas_stream_cipher_t const *stream_cipher, uint8_t out[4])
{
DevAssert(stream_cipher != NULL);
DevAssert(stream_cipher->message != NULL);
@@ -49,7 +49,7 @@ int nas_stream_encrypt_eia2(nas_stream_cipher_t *stream_cipher, uint8_t out[4])
DevAssert((stream_cipher->blength & 0x7) == 0);
aes_128_t k_iv = {0};
memcpy(&k_iv.key, stream_cipher->key, sizeof(k_iv.key));
memcpy(k_iv.key, stream_cipher->key, sizeof(k_iv.key));
k_iv.type = AES_INITIALIZATION_VECTOR_8;
k_iv.iv8.d.bearer = stream_cipher->bearer;
k_iv.iv8.d.direction = stream_cipher->direction;
@@ -61,6 +61,5 @@ int nas_stream_encrypt_eia2(nas_stream_cipher_t *stream_cipher, uint8_t out[4])
aes_128_cbc_cmac(&k_iv, msg, sizeof(result), result);
memcpy(out, result, 4);
return 0;
}
+29
View File
@@ -0,0 +1,29 @@
/*
* 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 OAI_NAS_STREAM_EIA2_H
#define OAI_NAS_STREAM_EIA2_H
#include "secu_defs.h"
void nas_stream_encrypt_eia2(nas_stream_cipher_t const* stream_cipher, uint8_t out[4]);
#endif
+38 -68
View File
@@ -19,78 +19,48 @@
* contact@openairinterface.org
*/
#include "secu_defs.h"
#include "kdf.h"
#ifndef NAS_UE
int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB)
#include "common/utils/assertions.h"
#include "common/utils/LOG/log.h"
#include "nas_stream_eea0.h"
#include "nas_stream_eea1.h"
#include "nas_stream_eea2.h"
#include "nas_stream_eia1.h"
#include "nas_stream_eia2.h"
void stream_compute_integrity(eia_alg_id_e alg, nas_stream_cipher_t const* stream_cipher, uint8_t out[4])
{
uint8_t s[7] = {0};
// FC
s[0] = FC_KENB;
// P0 = Uplink NAS count
s[1] = (nas_count & 0xff000000) >> 24;
s[2] = (nas_count & 0x00ff0000) >> 16;
s[3] = (nas_count & 0x0000ff00) >> 8;
s[4] = (nas_count & 0x000000ff);
// Length of NAS count
s[5] = 0x00;
s[6] = 0x04;
// kdf(kasme, 32, s, 7, keNB, 32);
byte_array_t data = {.buf = s, .len = 7};
kdf(kasme, data, 32, keNB);
return 0;
}
#endif
int derive_keNB_star(
const uint8_t *kenb_32,
const uint16_t pci,
const uint32_t earfcn_dl,
const bool is_rel8_only,
uint8_t *kenb_star)
{
// see 33.401 section A.5 KeNB* derivation function
uint8_t s[10] = {0};
byte_array_t data = {.buf = s};
// FC = 0x13
s[0] = FC_KENB_STAR;
// P0 = PCI (target physical cell id)
s[1] = (pci & 0x0000ff00) >> 8;
s[2] = (pci & 0x000000ff);
// L0 = length of PCI (i.e. 0x00 0x02)
s[3] = 0x00;
s[4] = 0x02;
// P1 = EARFCN-DL (target physical cell downlink frequency)
if (is_rel8_only) {
s[5] = (earfcn_dl & 0x0000ff00) >> 8;
s[6] = (earfcn_dl & 0x000000ff);
s[7] = 0x00;
s[8] = 0x02;
// kdf (kenb_32, 32, s, 9, kenb_star, 32);
data.len = 9;
if (alg == EIA0_ALG_ID) {
LOG_E(OSA, "Provided integrity algorithm is currently not supported = %u\n", alg);
} else if (alg == EIA1_128_ALG_ID) {
LOG_D(OSA, "EIA1 algorithm applied for integrity\n");
nas_stream_encrypt_eia1(stream_cipher, out);
} else if (alg == EIA2_128_ALG_ID) {
LOG_D(OSA, "EIA2 algorithm applied for integrity\n");
nas_stream_encrypt_eia2(stream_cipher, out);
} else {
s[5] = (earfcn_dl & 0x00ff0000) >> 16;
s[6] = (earfcn_dl & 0x0000ff00) >> 8;
s[7] = (earfcn_dl & 0x000000ff);
s[8] = 0x00;
s[9] = 0x03;
//kdf (kenb_32, 32, s, 10, kenb_star, 32);
data.len = 10;
LOG_E(OSA, "Provided integrity algorithm is currently not supported = %u\n", alg);
DevAssert(0 != 0 && "Unknown Algorithm type");
}
}
void stream_compute_encrypt(eea_alg_id_e alg, nas_stream_cipher_t const* stream_cipher, uint8_t* out)
{
if (alg == EEA0_ALG_ID) {
LOG_D(OSA, "EEA0 algorithm applied for encryption\n");
nas_stream_encrypt_eea0(stream_cipher, out);
} else if (alg == EEA1_128_ALG_ID) {
LOG_D(OSA, "EEA1 algorithm applied for encryption\n");
nas_stream_encrypt_eea1(stream_cipher, out);
} else if (alg == EEA2_128_ALG_ID) {
LOG_D(OSA, "EEA2 algorithm applied for encryption\n");
nas_stream_encrypt_eea2(stream_cipher, out);
} else {
LOG_E(OSA, "Provided encrypt algorithm is currently not supported = %u\n", alg);
DevAssert(0 != 0 && "Unknown Algorithm type");
}
kdf (kenb_32, data, 32, kenb_star);
// L1 length of EARFCN-DL (i.e. L1 = 0x00 0x02 if EARFCN-DL is between 0 and 65535, and L1 = 0x00 0x03 if EARFCN-DL is between 65536 and 262143)
// NOTE: The length of EARFCN-DL cannot be generally set to 3 bytes for backward compatibility reasons: A Rel-8
// entity (UE or eNB) would always assume an input parameter length of 2 bytes for the EARFCN-DL. This
// would lead to different derived keys if another entity assumed an input parameter length of 3 bytes for the
// EARFCN-DL.
return 0;
}
+25 -43
View File
@@ -22,47 +22,9 @@
#ifndef SECU_DEFS_H_
#define SECU_DEFS_H_
#include "security_types.h"
#include <stdbool.h>
#include <stdint.h>
#define EIA0_ALG_ID 0x00
#define EIA1_128_ALG_ID 0x01
#define EIA2_128_ALG_ID 0x02
#define EEA0_ALG_ID 0x00
#define EEA1_128_ALG_ID 0x01
#define EEA2_128_ALG_ID 0x02
#define SECU_DIRECTION_UPLINK 0
#define SECU_DIRECTION_DOWNLINK 1
int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB);
int derive_keNB_star(const uint8_t *kenb_32, const uint16_t pci, const uint32_t earfcn_dl,
const bool is_rel8_only, uint8_t * kenb_star);
int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
const uint8_t kasme[32], uint8_t *knas);
#define derive_key_nas_enc(aLGiD, kASME, kNAS) \
derive_key_nas(NAS_ENC_ALG, aLGiD, kASME, kNAS)
#define derive_key_nas_int(aLGiD, kASME, kNAS) \
derive_key_nas(NAS_INT_ALG, aLGiD, kASME, kNAS)
#define derive_key_rrc_enc(aLGiD, kASME, kNAS) \
derive_key_nas(RRC_ENC_ALG, aLGiD, kASME, kNAS)
#define derive_key_rrc_int(aLGiD, kASME, kNAS) \
derive_key_nas(RRC_INT_ALG, aLGiD, kASME, kNAS)
#define derive_key_up_enc(aLGiD, kASME, kNAS) \
derive_key_nas(UP_ENC_ALG, aLGiD, kASME, kNAS)
#define derive_key_up_int(aLGiD, kASME, kNAS) \
derive_key_nas(UP_INT_ALG, aLGiD, kASME, kNAS)
#define SECU_DIRECTION_UPLINK 0
#define SECU_DIRECTION_DOWNLINK 1
@@ -77,14 +39,34 @@ typedef struct {
uint32_t blength;
} nas_stream_cipher_t;
int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t *out);
/*!
* @brief Encrypt/Decrypt a block of data based on the provided algorithm
* @param[in] algorithm Algorithm used to encrypt the data
* Possible values are:
* - EIA0_ALG_ID for NULL encryption
* - EIA1_128_ALG_ID for SNOW-3G encryption (not avalaible right now)
* - EIA2_128_ALG_ID for 128 bits AES LTE encryption
* @param[in] stream_cipher All parameters used to compute the encrypted block of data
* @param[out] out The encrypted block of data
*/
int nas_stream_encrypt_eia1(nas_stream_cipher_t *stream_cipher, uint8_t out[4]);
typedef enum {
EIA0_ALG_ID = 0x00,
EIA1_128_ALG_ID = 0x01,
EIA2_128_ALG_ID = 0x02,
END_EIA0_ALG_ID,
} eia_alg_id_e;
int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t *out);
void stream_compute_integrity(eia_alg_id_e alg, nas_stream_cipher_t const *stream_cipher, uint8_t out[4]);
int nas_stream_encrypt_eia2(nas_stream_cipher_t *stream_cipher, uint8_t out[4]);
typedef enum {
EEA0_ALG_ID = 0x00,
EEA1_128_ALG_ID = 0x01,
EEA2_128_ALG_ID = 0x02,
#undef SECU_DEBUG
END_EEA_ALG_ID
} eea_alg_id_e;
void stream_compute_encrypt(eea_alg_id_e alg, nas_stream_cipher_t const *stream_cipher, uint8_t *out);
#endif /* SECU_DEFS_H_ */
+1 -2
View File
@@ -52,8 +52,7 @@ void eea1_encrypt(uint8_t direction, uint32_t count,
nas_cipher->blength = length;
nas_cipher->message = message;
if (nas_stream_encrypt_eea1(nas_cipher, result) != 0)
fail("Fail: nas_stream_encrypt_eea1\n");
stream_compute_encrypt(EEA1_128_ALG_ID, nas_cipher, result);
if (compare_buffer(result, byte_length, expected, byte_length) != 0) {
fail("Fail: eea1_encrypt\n");
+1 -3
View File
@@ -25,7 +25,6 @@
#include <unistd.h>
#include "test_util.h"
#include "secu_defs.h"
static
@@ -52,8 +51,7 @@ void eea2_encrypt(uint8_t direction, uint32_t count,
nas_cipher->blength = length;
nas_cipher->message = message;
if (nas_stream_encrypt_eea2(nas_cipher, result) != 0)
fail("Fail: nas_stream_encrypt_eea2\n");
nas_stream_encrypt_eea2(nas_cipher, result);
if (compare_buffer(result, byte_length, expected, byte_length) != 0) {
fail("Fail: eea2_encrypt\n");