OSA SECU harmonization
This commit is contained in:
+17
-26
@@ -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
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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) ;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -23,8 +23,6 @@
|
||||
|
||||
#include "commonDef.h"
|
||||
|
||||
#include "security_types.h"
|
||||
|
||||
#include "queue.h"
|
||||
|
||||
#ifndef COMMON_TYPES_H_
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++){
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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_ */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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_ */
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user