Added kdf common

Use kdf functions in 5G KDF

Moved EPS KDF function to new KDF structure
This commit is contained in:
David Rupprecht 2021-07-27 17:52:02 +02:00 committed by David Rupprecht
parent 15eaef21e2
commit bce6b5cc0f
8 changed files with 726 additions and 96 deletions

View File

@ -18,7 +18,21 @@
*****************************************************************************/
#include "srsran/common/common.h"
#include "srsran/srslog/srslog.h"
#include <vector>
#define AKA_RAND_LEN 16
#define AKA_AUTN_LEN 16
#define AKA_AUTS_LEN 14
#define RES_MAX_LEN 16
#define MAC_LEN 8
#define IK_LEN 16
#define CK_LEN 16
#define AK_LEN 6
#define SQN_LEN 6
#define KEY_LEN 32
namespace srsran {
typedef enum {
@ -73,16 +87,55 @@ struct as_security_config_t {
CIPHERING_ALGORITHM_ID_ENUM cipher_algo;
};
template <typename... Args>
void log_error(const char* format, Args&&... args)
{
srslog::fetch_basic_logger("SEC").error(format, std::forward<Args>(args)...);
}
template <typename... Args>
void log_warning(const char* format, Args&&... args)
{
srslog::fetch_basic_logger("SEC").warning(format, std::forward<Args>(args)...);
}
template <typename... Args>
void log_info(const char* format, Args&&... args)
{
srslog::fetch_basic_logger("SEC").info(format, std::forward<Args>(args)...);
}
template <typename... Args>
void log_debug(const char* format, Args&&... args)
{
srslog::fetch_basic_logger("SEC").debug(format, std::forward<Args>(args)...);
}
/******************************************************************************
* Key Generation
*****************************************************************************/
uint8_t security_generate_k_asme(uint8_t* ck,
uint8_t* ik,
uint8_t* ak,
uint8_t* sqn,
uint16_t mcc,
uint16_t mnc,
uint8_t* k_asme);
int kdf_common(const uint8_t fc, const std::array<uint8_t, 32>& key, const std::vector<uint8_t>& P, uint8_t* output);
int kdf_common(const uint8_t fc,
const std::array<uint8_t, 32>& key,
const std::vector<uint8_t>& P0,
const std::vector<uint8_t>& P1,
uint8_t* output);
int kdf_common(const uint8_t fc,
const std::array<uint8_t, 32>& key,
const std::vector<uint8_t>& P0,
const std::vector<uint8_t>& P1,
const std::vector<uint8_t>& P3,
uint8_t* output);
uint8_t
security_generate_k_asme(uint8_t* ck, uint8_t* ik, uint8_t* ak_xor_sqn, uint16_t mcc, uint16_t mnc, uint8_t* k_asme);
uint8_t security_generate_k_ausf(uint8_t* ck,
uint8_t* ik,
uint8_t* ak_xor_sqn,
const char* serving_network_name,
uint8_t* k_ausf);
uint8_t security_generate_k_enb(uint8_t* k_asme, uint32_t nas_count, uint8_t* k_enb);

View File

@ -18,12 +18,12 @@
#include "polarssl/aes.h"
#include "polarssl/sha256.h"
void sha256(const unsigned char* key,
size_t keylen,
const unsigned char* input,
size_t ilen,
unsigned char output[32],
int is224)
inline void sha256(const unsigned char* key,
size_t keylen,
const unsigned char* input,
size_t ilen,
unsigned char output[32],
int is224)
{
sha256_hmac(key, keylen, input, ilen, output, is224);
}
@ -40,33 +40,33 @@ typedef mbedtls_aes_context aes_context;
#define AES_ENCRYPT 1
#define AES_DECRYPT 0
int aes_setkey_enc(aes_context* ctx, const unsigned char* key, unsigned int keysize)
inline int aes_setkey_enc(aes_context* ctx, const unsigned char* key, unsigned int keysize)
{
return mbedtls_aes_setkey_enc(ctx, key, keysize);
}
int aes_crypt_ecb(aes_context* ctx, int mode, const unsigned char input[16], unsigned char output[16])
inline int aes_crypt_ecb(aes_context* ctx, int mode, const unsigned char input[16], unsigned char output[16])
{
return mbedtls_aes_crypt_ecb(ctx, mode, input, output);
}
int aes_crypt_ctr(aes_context* ctx,
size_t length,
size_t* nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char* input,
unsigned char* output)
inline int aes_crypt_ctr(aes_context* ctx,
size_t length,
size_t* nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char* input,
unsigned char* output)
{
return mbedtls_aes_crypt_ctr(ctx, length, nc_off, nonce_counter, stream_block, input, output);
}
void sha256(const unsigned char* key,
size_t keylen,
const unsigned char* input,
size_t ilen,
unsigned char output[32],
int is224)
inline void sha256(const unsigned char* key,
size_t keylen,
const unsigned char* input,
size_t ilen,
unsigned char output[32],
int is224)
{
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), key, keylen, input, ilen, output);
}

View File

@ -192,22 +192,18 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_nas(uint8*
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 s[7];
if (k_asme != NULL && k_nas_enc != NULL) { //{}
if (enc_alg_id != LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_EEA0) {
// Construct S for KNASenc
s[0] = 0x15; // FC
s[1] = 0x01; // P0
s[2] = 0x00; // First byte of L0
s[3] = 0x01; // Second byte of L0
s[4] = enc_alg_id; // P1
s[5] = 0x00; // First byte of L1
s[6] = 0x01; // Second byte of L1
if (k_asme != NULL && k_nas_enc != NULL) {
// Construct S for KNASenc
s[0] = 0x15; // FC
s[1] = 0x01; // P0
s[2] = 0x00; // First byte of L0
s[3] = 0x01; // Second byte of L0
s[4] = enc_alg_id; // P1
s[5] = 0x00; // First byte of L1
s[6] = 0x01; // Second byte of L1
// Derive KNASenc
sha256(k_asme, 32, s, 7, k_nas_enc, 0);
} else {
memset(k_nas_enc, 0, 32);
}
// Derive KNASenc
sha256(k_asme, 32, s, 7, k_nas_enc, 0);
}
if (k_asme != NULL && k_nas_int != NULL) {

View File

@ -13,8 +13,11 @@
#include "srsran/common/security.h"
#include "srsran/common/liblte_security.h"
#include "srsran/common/s3g.h"
#include "srsran/common/ssl.h"
#include "srsran/config.h"
#include <arpa/inet.h>
#ifdef HAVE_MBEDTLS
#include "mbedtls/md5.h"
#endif
@ -22,36 +25,190 @@
#include "polarssl/md5.h"
#endif
#define FC_EPS_K_ASME_DERIVATION 0x10
#define FC_EPS_K_ENB_DERIVATION 0x11
#define FC_EPS_NH_DERIVATION 0x12
#define FC_EPS_K_ENB_STAR_DERIVATION 0x13
#define FC_EPS_ALGORITHM_KEY_DERIVATION 0x15
#define ALGO_EPS_DISTINGUISHER_NAS_ENC_ALG 0x01
#define ALGO_EPS_DISTINGUISHER_NAS_INT_ALG 0x02
#define ALGO_EPS_DISTINGUISHER_RRC_ENC_ALG 0x03
#define ALGO_EPS_DISTINGUISHER_RRC_INT_ALG 0x04
#define ALGO_EPS_DISTINGUISHER_UP_ENC_ALG 0x05
#define ALGO_EPS_DISTINGUISHER_UP_INT_ALG 0x06
#define FC_5G_ALGORITHM_KEY_DERIVATION 0x69
#define FC_5G_KAUSF_DERIVATION 0x6A
#define FC_5G_RES_STAR_DERIVATION 0x6B
#define FC_5G_KSEAF_DERIVATION 0x6C
#define FC_5G_KAMF_DERIVATION 0x6D
#define FC_5G_KGNB_KN3IWF_DERIVATION 0x6E
#define FC_5G_NH_GNB_DERIVATION 0x6F
#define ALGO_5G_DISTINGUISHER_NAS_ENC_ALG 0x01
#define ALGO_5G_DISTINGUISHER_NAS_INT_ALG 0x02
#define ALGO_5G_DISTINGUISHER_RRC_ENC_ALG 0x03
#define ALGO_5G_DISTINGUISHER_RRC_INT_ALG 0x04
#define ALGO_5G_DISTINGUISHER_UP_ENC_ALG 0x05
#define ALGO_5G_DISTINGUISHER_UP_INT_ALG 0x06
namespace srsran {
/******************************************************************************
* Key Generation
*****************************************************************************/
uint8_t security_generate_k_asme(uint8_t* ck,
uint8_t* ik,
uint8_t* ak,
uint8_t* sqn,
uint16_t mcc,
uint16_t mnc,
uint8_t* k_asme)
uint8_t
security_generate_k_asme(uint8_t* ck, uint8_t* ik, uint8_t* ak_xor_sqn_, uint16_t mcc, uint16_t mnc, uint8_t* k_asme)
{
return liblte_security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme);
if (ck == NULL || ik == NULL || ak_xor_sqn_ == NULL || k_asme == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
// The input key Key shall be equal to the concatenation CK || IK of CK and IK.
memcpy(key.data(), ck, 16);
memcpy(key.data() + 16, ik, 16);
// Serving Network id
std::vector<uint8_t> sn_id;
sn_id.resize(3);
sn_id[0] = (mcc & 0x00F0) | ((mcc & 0x0F00) >> 8); // First byte of P0
if ((mnc & 0xFF00) == 0xFF00) {
// 2-digit MNC
sn_id[1] = 0xF0 | (mcc & 0x000F); // Second byte of P0
sn_id[2] = ((mnc & 0x000F) << 4) | ((mnc & 0x00F0) >> 4); // Third byte of P0
} else {
// 3-digit MNC
sn_id[1] = ((mnc & 0x000F) << 4) | (mcc & 0x000F); // Second byte of P0
sn_id[2] = ((mnc & 0x00F0)) | ((mnc & 0x0F00) >> 8); // Third byte of P0
}
// AK XOR SQN
std::vector<uint8_t> ak_xor_sqn;
ak_xor_sqn.resize(AK_LEN);
memcpy(ak_xor_sqn.data(), ak_xor_sqn_, ak_xor_sqn.size());
uint8_t output[32];
if (kdf_common(FC_EPS_K_ASME_DERIVATION, key, sn_id, ak_xor_sqn, output) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
memcpy(k_asme, output, 32);
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_enb(uint8_t* k_asme, uint32_t nas_count, uint8_t* k_enb)
uint8_t security_generate_k_ausf(uint8_t* ck,
uint8_t* ik,
uint8_t* ak_xor_sqn_,
const char* serving_network_name,
uint8_t* k_ausf)
{
return liblte_security_generate_k_enb(k_asme, nas_count, k_enb);
if (ck == NULL || ik == NULL || ak_xor_sqn_ == NULL || serving_network_name == NULL || k_ausf == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
// The input key Key shall be equal to the concatenation CK || IK of CK and IK.
memcpy(key.data(), ck, 16);
memcpy(key.data() + 16, ik, 16);
// Serving Network Name
std::vector<uint8_t> ssn;
ssn.resize(strlen(serving_network_name));
memcpy(ssn.data(), serving_network_name, ssn.size());
// AK XOR SQN
std::vector<uint8_t> ak_xor_sqn;
ak_xor_sqn.resize(AK_LEN);
memcpy(ak_xor_sqn.data(), ak_xor_sqn_, ak_xor_sqn.size());
uint8_t output[32];
if (kdf_common(FC_5G_RES_STAR_DERIVATION, key, ssn, ak_xor_sqn, output) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
memcpy(k_ausf, output, 32);
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_enb_star(uint8_t* k_enb, uint32_t pci, uint32_t earfcn, uint8_t* k_enb_star)
uint8_t security_generate_k_enb(uint8_t* k_asme, uint32_t nas_count_, uint8_t* k_enb)
{
return liblte_security_generate_k_enb_star(k_enb, pci, earfcn, k_enb_star);
if (k_asme == NULL || k_enb == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_asme, 32);
// NAS Count
std::vector<uint8_t> nas_count;
nas_count.resize(4);
nas_count[0] = (nas_count_ >> 24) & 0xFF;
nas_count[1] = (nas_count_ >> 16) & 0xFF;
nas_count[2] = (nas_count_ >> 8) & 0xFF;
nas_count[3] = nas_count_ & 0xFF;
if (kdf_common(FC_EPS_K_ENB_DERIVATION, key, nas_count, k_enb) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_nh(uint8_t* k_asme, uint8_t* sync, uint8_t* nh)
uint8_t security_generate_k_enb_star(uint8_t* k_enb, uint32_t pci_, uint32_t earfcn_, uint8_t* k_enb_star)
{
return liblte_security_generate_nh(k_asme, sync, nh);
if (k_enb == NULL || k_enb_star == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_enb, 32);
// PCI
std::vector<uint8_t> pci;
pci.resize(2);
pci[0] = (pci_ >> 8) & 0xFF;
pci[1] = pci_ & 0xFF;
// EARFCN
std::vector<uint8_t> earfcn;
earfcn.resize(2);
earfcn[0] = (earfcn_ >> 8) & 0xFF;
earfcn[1] = earfcn_ & 0xFF;
if (kdf_common(FC_EPS_K_ENB_STAR_DERIVATION, key, pci, earfcn, k_enb_star) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_nh(uint8_t* k_asme, uint8_t* sync_, uint8_t* nh)
{
if (k_asme == NULL || sync_ == NULL || nh == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_asme, 32);
// PCI
std::vector<uint8_t> sync;
sync.resize(32);
memcpy(sync.data(), sync_, 32);
if (kdf_common(FC_EPS_NH_DERIVATION, key, sync, nh) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_nas(uint8_t* k_asme,
@ -60,11 +217,47 @@ uint8_t security_generate_k_nas(uint8_t* k_asme,
uint8_t* k_nas_enc,
uint8_t* k_nas_int)
{
return liblte_security_generate_k_nas(k_asme,
(LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id,
(LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id,
k_nas_enc,
k_nas_int);
if (k_asme == NULL || k_nas_enc == NULL || k_nas_int == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_asme, 32);
// Derive NAS ENC
// algorithm type distinguisher
std::vector<uint8_t> algo_distinguisher;
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_NAS_ENC_ALG;
// algorithm type distinguisher
std::vector<uint8_t> algorithm_identity;
algorithm_identity.resize(1);
algorithm_identity[0] = enc_alg_id;
if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_nas_enc) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
// Derive NAS INT
// algorithm type distinguisher
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_NAS_INT_ALG;
// algorithm type distinguisher
algorithm_identity.resize(1);
algorithm_identity[0] = int_alg_id;
// Derive NAS int
if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_nas_int) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_rrc(uint8_t* k_enb,
@ -73,11 +266,47 @@ uint8_t security_generate_k_rrc(uint8_t* k_enb,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int)
{
return liblte_security_generate_k_rrc(k_enb,
(LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id,
(LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id,
k_rrc_enc,
k_rrc_int);
if (k_enb == NULL || k_rrc_enc == NULL || k_rrc_int == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_enb, 32);
// Derive RRC ENC
// algorithm type distinguisher
std::vector<uint8_t> algo_distinguisher;
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_RRC_ENC_ALG;
// algorithm type distinguisher
std::vector<uint8_t> algorithm_identity;
algorithm_identity.resize(1);
algorithm_identity[0] = enc_alg_id;
if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_rrc_enc) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
// Derive RRC INT
// algorithm type distinguisher
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_RRC_INT_ALG;
// algorithm type distinguisher
algorithm_identity.resize(1);
algorithm_identity[0] = int_alg_id;
// Derive RRC int
if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_rrc_int) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_up(uint8_t* k_enb,
@ -86,11 +315,74 @@ uint8_t security_generate_k_up(uint8_t* k_enb,
uint8_t* k_up_enc,
uint8_t* k_up_int)
{
return liblte_security_generate_k_up(k_enb,
(LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id,
(LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id,
k_up_enc,
k_up_int);
if (k_enb == NULL || k_up_enc == NULL || k_up_int == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_enb, 32);
// Derive UP ENC
// algorithm type distinguisher
std::vector<uint8_t> algo_distinguisher;
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_UP_ENC_ALG;
// algorithm type distinguisher
std::vector<uint8_t> algorithm_identity;
algorithm_identity.resize(1);
algorithm_identity[0] = enc_alg_id;
if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_up_enc) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
// Derive UP INT
// algorithm type distinguisher
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_EPS_DISTINGUISHER_UP_INT_ALG;
// algorithm type distinguisher
algorithm_identity.resize(1);
algorithm_identity[0] = int_alg_id;
// Derive UP int
if (kdf_common(FC_EPS_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_up_int) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_count_)
{
if (k_enb == NULL || sk_gnb == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_enb, 32);
// SCG Count
std::vector<uint8_t> scg_count;
scg_count.resize(2);
scg_count[0] = (scg_count_ >> 8) & 0xFF; // first byte of P0
scg_count[1] = scg_count_ & 0xFF; // second byte of P0
// Derive sk_gnb
uint8_t output[32];
if (kdf_common(0x1C, key, scg_count, output) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
memcpy(sk_gnb, output, 32);
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_nr_rrc(uint8_t* k_gnb,
@ -99,11 +391,47 @@ uint8_t security_generate_k_nr_rrc(uint8_t* k_gnb,
uint8_t* k_rrc_enc,
uint8_t* k_rrc_int)
{
return liblte_security_generate_k_nr_rrc(k_gnb,
(LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id,
(LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id,
k_rrc_enc,
k_rrc_int);
if (k_gnb == NULL || k_rrc_enc == NULL || k_rrc_int == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_gnb, 32);
// Derive RRC ENC
// algorithm type distinguisher
std::vector<uint8_t> algo_distinguisher;
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_RRC_ENC_ALG;
// algorithm type distinguisher
std::vector<uint8_t> algorithm_identity;
algorithm_identity.resize(1);
algorithm_identity[0] = enc_alg_id;
if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_rrc_enc) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
// Derive RRC INT
// algorithm type distinguisher
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_RRC_INT_ALG;
// algorithm type distinguisher
algorithm_identity.resize(1);
algorithm_identity[0] = int_alg_id;
// Derive RRC int
if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_rrc_int) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_k_nr_up(uint8_t* k_gnb,
@ -112,18 +440,208 @@ uint8_t security_generate_k_nr_up(uint8_t* k_gnb,
uint8_t* k_up_enc,
uint8_t* k_up_int)
{
return liblte_security_generate_k_nr_up(k_gnb,
(LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM)enc_alg_id,
(LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM)int_alg_id,
k_up_enc,
k_up_int);
if (k_gnb == NULL || k_up_enc == NULL || k_up_int == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
memcpy(key.data(), k_gnb, 32);
// Derive UP ENC
// algorithm type distinguisher
std::vector<uint8_t> algo_distinguisher;
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_UP_ENC_ALG;
// algorithm type distinguisher
std::vector<uint8_t> algorithm_identity;
algorithm_identity.resize(1);
algorithm_identity[0] = enc_alg_id;
if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_up_enc) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
// Derive UP INT
// algorithm type distinguisher
algo_distinguisher.resize(1);
algo_distinguisher[0] = ALGO_5G_DISTINGUISHER_UP_INT_ALG;
// algorithm type distinguisher
algorithm_identity.resize(1);
algorithm_identity[0] = int_alg_id;
// Derive UP int
if (kdf_common(FC_5G_ALGORITHM_KEY_DERIVATION, key, algo_distinguisher, algorithm_identity, k_up_int) !=
SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
uint8_t security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_count)
uint8_t security_generate_res_star(uint8_t* ck,
uint8_t* ik,
const char* serving_network_name,
uint8_t* rand_,
uint8_t* res_,
size_t res_len_,
uint8_t* res_star)
{
return liblte_security_generate_sk_gnb(k_enb, sk_gnb, scg_count);
if (ck == NULL || ik == NULL || serving_network_name == NULL || rand_ == NULL || res_ == NULL || res_star == NULL) {
log_error("Invalid inputs");
return SRSRAN_ERROR;
}
std::array<uint8_t, 32> key;
// The input key Key shall be equal to the concatenation CK || IK of CK and IK.
memcpy(key.data(), ck, 16);
memcpy(key.data() + 16, ik, 16);
// Serving Network Name
std::vector<uint8_t> ssn;
ssn.resize(strlen(serving_network_name));
memcpy(ssn.data(), serving_network_name, strlen(serving_network_name));
// RAND
std::vector<uint8_t> rand;
rand.resize(AKA_RAND_LEN);
memcpy(rand.data(), rand_, rand.size());
// RES
std::vector<uint8_t> res;
res.resize(res_len_);
memcpy(res.data(), res_, res.size());
uint8_t output[32];
if (kdf_common(FC_5G_RES_STAR_DERIVATION, key, ssn, rand, res, output) != SRSRAN_SUCCESS) {
log_error("Failed to run kdf_common");
return SRSRAN_ERROR;
}
memcpy(res_star, output + 16, 16);
return SRSRAN_SUCCESS;
}
int kdf_common(const uint8_t fc, const std::array<uint8_t, 32>& key, const std::vector<uint8_t>& P0, uint8_t* output)
{
uint8_t* s;
uint32_t s_len = 1 + P0.size() + 2;
s = (uint8_t*)calloc(s_len, sizeof(uint8_t));
if (s == nullptr) {
log_error("Unable to allocate memory in %s()", __FUNCTION__);
return SRSRAN_ERROR;
}
uint32_t i = 0;
s[i] = fc; // FC
i++;
// P0
memcpy(&s[i], P0.data(), P0.size());
i += P0.size();
uint16_t p0_length_value = htons(P0.size());
memcpy(&s[i], &p0_length_value, sizeof(p0_length_value));
i += sizeof(p0_length_value);
sha256(key.data(), key.size(), s, i, output, 0);
free(s);
return SRSRAN_SUCCESS;
}
int kdf_common(const uint8_t fc,
const std::array<uint8_t, 32>& key,
const std::vector<uint8_t>& P0,
const std::vector<uint8_t>& P1,
uint8_t* output)
{
uint8_t* s;
uint32_t s_len = 1 + P0.size() + 2 + P1.size() + 2;
s = (uint8_t*)calloc(s_len, sizeof(uint8_t));
if (s == nullptr) {
log_error("Unable to allocate memory in %s()", __FUNCTION__);
return SRSRAN_ERROR;
}
uint32_t i = 0;
s[i] = fc; // FC
i++;
// P0
memcpy(&s[i], P0.data(), P0.size());
i += P0.size();
uint16_t p0_length_value = htons(P0.size());
memcpy(&s[i], &p0_length_value, sizeof(p0_length_value));
i += sizeof(p0_length_value);
// P1
memcpy(&s[i], P1.data(), P1.size());
i += P1.size();
uint16_t p1_length_value = htons(P1.size());
memcpy(&s[i], &p1_length_value, sizeof(p1_length_value));
i += sizeof(p1_length_value);
sha256(key.data(), key.size(), s, i, output, 0);
free(s);
return SRSRAN_SUCCESS;
}
int kdf_common(const uint8_t fc,
const std::array<uint8_t, 32>& key,
const std::vector<uint8_t>& P0,
const std::vector<uint8_t>& P1,
const std::vector<uint8_t>& P2,
uint8_t* output)
{
uint8_t* s;
uint32_t s_len = 1 + P0.size() + 2 + P1.size() + 2 + P2.size() + 2;
s = (uint8_t*)calloc(s_len, sizeof(uint8_t));
if (s == nullptr) {
log_error("Unable to allocate memory in %s()", __FUNCTION__);
return SRSRAN_ERROR;
}
uint32_t i = 0;
s[i] = fc; // FC
i++;
// P0
memcpy(&s[i], P0.data(), P0.size());
i += P0.size();
uint16_t p0_length_value = htons(P0.size());
memcpy(&s[i], &p0_length_value, sizeof(p0_length_value));
i += sizeof(p0_length_value);
// P1
memcpy(&s[i], P1.data(), P1.size());
i += P1.size();
uint16_t p1_length_value = htons(P1.size());
memcpy(&s[i], &p1_length_value, sizeof(p1_length_value));
i += sizeof(p1_length_value);
// P2
memcpy(&s[i], P2.data(), P2.size());
i += P2.size();
uint16_t p2_length_value = htons(P2.size());
memcpy(&s[i], &p2_length_value, sizeof(p2_length_value));
i += sizeof(p2_length_value);
sha256(key.data(), key.size(), s, i, output, 0);
free(s);
return SRSRAN_SUCCESS;
}
/******************************************************************************
* Integrity Protection
*****************************************************************************/
@ -185,7 +703,6 @@ uint8_t security_128_eea1(uint8_t* key,
uint32_t msg_len,
uint8_t* msg_out)
{
return liblte_security_encryption_eea1(key, count, bearer, direction, msg, msg_len * 8, msg_out);
}
@ -197,7 +714,6 @@ uint8_t security_128_eea2(uint8_t* key,
uint32_t msg_len,
uint8_t* msg_out)
{
return liblte_security_encryption_eea2(key, count, bearer, direction, msg, msg_len * 8, msg_out);
}
@ -209,7 +725,6 @@ uint8_t security_128_eea3(uint8_t* key,
uint32_t msg_len,
uint8_t* msg_out)
{
return liblte_security_encryption_eea3(key, count, bearer, direction, msg, msg_len * 8, msg_out);
}

View File

@ -111,8 +111,12 @@ int test_generate_k_asme()
uint16_t mcc = 61441; // MCC 001
uint16_t mnc = 65281; // MNC 01
uint8_t ak_xor_sqn[6];
for (uint32_t i = 0; i < 6; i++) {
ak_xor_sqn[i] = sqn[i] ^ ak[i];
}
// Generate K_asme
security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme_o);
security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme_o);
uint8_t k_asme[] = {0xd5, 0xef, 0x4d, 0x8f, 0x33, 0x26, 0x69, 0x02, 0x29, 0x5d, 0x42, 0xf3, 0x22, 0xa2, 0xf2, 0xcf,
0x11, 0xfb, 0x2c, 0xcc, 0x12, 0x4c, 0x09, 0xb4, 0xd8, 0x8d, 0x36, 0x15, 0x97, 0x03, 0x79, 0x90};
@ -138,9 +142,9 @@ int test_generate_k_nas()
k_nas_enc_o,
k_nas_int_o) == SRSRAN_SUCCESS);
uint8_t k_nas_enc[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t k_nas_enc[] = {0xcf, 0x7a, 0x27, 0xbe, 0xab, 0x1e, 0x78, 0xbf, 0x5b, 0xb1, 0xf9,
0x5b, 0x05, 0x82, 0x9a, 0x72, 0xe4, 0xcf, 0x7f, 0xec, 0xba, 0xd4,
0xb8, 0xc3, 0x7d, 0xb4, 0xa1, 0x90, 0xe1, 0x19, 0x22, 0x5c};
logger.info(k_nas_enc_o, 32, "K NAS ENC output:");
TESTASSERT(arrcmp(k_nas_enc, k_nas_enc_o, sizeof(k_nas_enc_o)) == 0);
@ -236,6 +240,48 @@ int test_generate_up_keys()
return SRSRAN_SUCCESS;
}
int test_generate_k_enb_star()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t k_enb_star_o[32];
uint8_t k_enb[] = {0xc4, 0xc7, 0xbc, 0x79, 0x8a, 0xb9, 0x4e, 0x3d, 0x35, 0x4c, 0xd6, 0x60, 0x8e, 0x79, 0xaa, 0x92,
0xf5, 0x56, 0x9d, 0xf4, 0x65, 0x19, 0x50, 0x78, 0x50, 0x05, 0x1e, 0x36, 0xf0, 0x18, 0xca, 0x5f};
TESTASSERT(srsran::security_generate_k_enb_star(k_enb, 32, 561, k_enb_star_o) == SRSRAN_SUCCESS);
uint8_t k_enb_star[] = {0x6f, 0x04, 0x54, 0x57, 0x7f, 0x55, 0x5c, 0xa7, 0x6f, 0x44, 0x9c,
0x2a, 0xc1, 0xda, 0x0f, 0x4f, 0xb7, 0xde, 0x4b, 0x94, 0x40, 0x11,
0x0f, 0xfb, 0xd1, 0x2f, 0x3a, 0x5d, 0x4d, 0xe1, 0x73, 0x50};
logger.info(k_enb_star_o, 32, "K ENB STAR:");
TESTASSERT(arrcmp(k_enb_star_o, k_enb_star, sizeof(k_enb_star)) == 0);
return SRSRAN_SUCCESS;
}
int test_generate_k_nh()
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
uint8_t nh_o[32];
uint8_t k_asme[] = {0xd5, 0xef, 0x4d, 0x8f, 0x33, 0x26, 0x69, 0x02, 0x29, 0x5d, 0x42, 0xf3, 0x22, 0xa2, 0xf2, 0xcf,
0x11, 0xfb, 0x2c, 0xcc, 0x12, 0x4c, 0x09, 0xb4, 0xd8, 0x8d, 0x36, 0x15, 0x97, 0x03, 0x79, 0x90};
uint8_t sync[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12};
TESTASSERT(srsran::security_generate_nh(k_asme, sync, nh_o) == SRSRAN_SUCCESS);
uint8_t nh[] = {0xc8, 0x55, 0x86, 0x64, 0x13, 0x07, 0x1b, 0x74, 0xab, 0xa0, 0x1c, 0x13, 0x2b, 0x94, 0x3e, 0x76,
0x98, 0xaa, 0x5c, 0x11, 0x76, 0x0d, 0x9b, 0xb1, 0x16, 0x2a, 0xb3, 0x13, 0xb1, 0x1c, 0x60, 0x51};
logger.info(nh_o, 32, "NH:");
TESTASSERT(arrcmp(nh_o, nh, sizeof(nh)) == 0);
return SRSRAN_SUCCESS;
}
int main(int argc, char** argv)
{
auto& logger = srslog::fetch_basic_logger("LOG", false);
@ -249,6 +295,8 @@ int main(int argc, char** argv)
TESTASSERT(test_generate_k_enb() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_rrc_keys() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_up_keys() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_enb_star() == SRSRAN_SUCCESS);
TESTASSERT(test_generate_k_nh() == SRSRAN_SUCCESS);
TESTASSERT(test_set_ksg() == SRSRAN_SUCCESS);
TESTASSERT(test_set_nr_rrc_up() == SRSRAN_SUCCESS);

View File

@ -302,8 +302,12 @@ void hss::gen_auth_info_answer_milenage(hss_ue_ctx_t* ue_ctx,
m_logger.debug(sqn, 6, "User SQN : ");
m_logger.debug(mac, 8, "User MAC : ");
uint8_t ak_xor_sqn[6];
for (int i = 0; i < 6; i++) {
ak_xor_sqn[i] = sqn[i] ^ ak[i];
}
// Generate K_asme
srsran::security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme);
srsran::security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme);
m_logger.debug("User MCC : %x MNC : %x ", mcc, mnc);
m_logger.debug(k_asme, 32, "User k_asme : ");
@ -396,8 +400,12 @@ void hss::gen_auth_info_answer_xor(hss_ue_ctx_t* ue_ctx, uint8_t* k_asme, uint8_
autn[8 + i] = mac[i];
}
uint8_t ak_xor_sqn[6];
for (int i = 0; i < 6; i++) {
ak_xor_sqn[i] = sqn[i] ^ ak[i];
}
// Generate K_asme
srsran::security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme);
srsran::security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme);
m_logger.debug("User MCC : %x MNC : %x ", mcc, mnc);
m_logger.debug(k_asme, 32, "User k_asme : ");

View File

@ -143,7 +143,7 @@ auth_result_t pcsc_usim::generate_authentication_response(uint8_t* rand,
logger.debug(ak, AK_LEN, "AK:");
logger.debug(sqn, SQN_LEN, "SQN:");
logger.debug("mcc=%d, mnc=%d", mcc, mnc);
security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme);
security_generate_k_asme(ck, ik, sqn, mcc, mnc, k_asme);
logger.info(k_asme, KEY_LEN, "K_ASME:");
ret = AUTH_OK;

View File

@ -159,8 +159,12 @@ auth_result_t usim::gen_auth_res_milenage(uint8_t* rand,
}
}
uint8_t ak_xor_sqn[6];
for (i = 0; i < 6; i++) {
ak_xor_sqn[i] = sqn[i] ^ ak[i];
}
// Generate K_asme
security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme);
security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme);
return result;
}
@ -225,8 +229,14 @@ auth_result_t usim::gen_auth_res_xor(uint8_t* rand,
logger.debug(sqn, 6, "sqn:");
logger.debug(amf, 2, "amf:");
logger.debug(mac, 8, "mac:");
uint8_t ak_xor_sqn[6];
for (uint32_t i = 0; i < 6; i++) {
ak_xor_sqn[i] = sqn[i] ^ ak[i];
}
// Generate K_asme
security_generate_k_asme(ck, ik, ak, sqn, mcc, mnc, k_asme_);
security_generate_k_asme(ck, ik, ak_xor_sqn, mcc, mnc, k_asme_);
return result;
}