From 306bb6b38b0a5d5eaff9c4f2d5b2ccd6d043f697 Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Fri, 22 Jan 2021 13:43:53 +0100 Subject: [PATCH] Added function for derive keys --- lib/include/srslte/common/liblte_security.h | 13 +++ lib/include/srslte/common/security.h | 14 +++ lib/src/common/liblte_security.cc | 109 ++++++++++++++++++++ lib/src/common/security.cc | 31 ++++++ lib/test/common/test_f12345.cc | 69 +++++++++++++ 5 files changed, 236 insertions(+) diff --git a/lib/include/srslte/common/liblte_security.h b/lib/include/srslte/common/liblte_security.h index 43d7a2553..180a66502 100644 --- a/lib/include/srslte/common/liblte_security.h +++ b/lib/include/srslte/common/liblte_security.h @@ -146,6 +146,7 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_up(uint8* uint8* k_up_enc, uint8* k_up_int); +LIBLTE_ERROR_ENUM liblte_security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_counter); /********************************************************************* Name: liblte_security_128_eia2 @@ -336,4 +337,16 @@ liblte_security_milenage_f2345(uint8* k, uint8* op, uint8* rand, uint8* res, uin // Functions LIBLTE_ERROR_ENUM liblte_security_milenage_f5_star(uint8* k, uint8* op, uint8* rand, uint8* ak); +LIBLTE_ERROR_ENUM liblte_security_generate_k_nr_rrc(uint8* k_gnb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + uint8* k_rrc_enc, + uint8* k_rrc_int); + +LIBLTE_ERROR_ENUM liblte_security_generate_k_nr_up(uint8* k_gnb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + uint8* k_up_enc, + uint8* k_up_int); + #endif // SRSLTE_LIBLTE_SECURITY_H diff --git a/lib/include/srslte/common/security.h b/lib/include/srslte/common/security.h index c6b6a9082..3595a0551 100644 --- a/lib/include/srslte/common/security.h +++ b/lib/include/srslte/common/security.h @@ -104,6 +104,20 @@ uint8_t security_generate_k_up(uint8_t* k_enb, uint8_t* k_up_enc, uint8_t* k_up_int); +uint8_t security_generate_k_nr_rrc(uint8_t* k_gnb, + CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + uint8_t* k_rrc_enc, + uint8_t* k_rrc_int); + +uint8_t security_generate_k_nr_up(uint8_t* k_gnb, + CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + uint8_t* k_up_enc, + uint8_t* k_up_int); + +uint8_t security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_count); + /****************************************************************************** * Integrity Protection *****************************************************************************/ diff --git a/lib/src/common/liblte_security.cc b/lib/src/common/liblte_security.cc index aba39008f..a1ca336fc 100644 --- a/lib/src/common/liblte_security.cc +++ b/lib/src/common/liblte_security.cc @@ -276,6 +276,115 @@ LIBLTE_ERROR_ENUM liblte_security_generate_k_rrc(uint8* return (err); } +LIBLTE_ERROR_ENUM liblte_security_generate_k_nr_rrc(uint8* k_gnb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + uint8* k_rrc_enc, + uint8* k_rrc_int) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 s[7]; + + if (k_gnb != NULL && k_rrc_enc != NULL && k_rrc_int != NULL) { + // Construct S for KRRCenc + s[0] = 0x69; // FC + s[1] = 0x03; // 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 KRRCenc + sha256(k_gnb, 32, s, 7, k_rrc_enc, 0); + + // Construct S for KRRCint + s[0] = 0x69; // FC + s[1] = 0x04; // P0 + s[2] = 0x00; // First byte of L0 + s[3] = 0x01; // Second byte of L0 + s[4] = int_alg_id; // P1 + s[5] = 0x00; // First byte of L1 + s[6] = 0x01; // Second byte of L1 + + // Derive KRRCint + sha256(k_gnb, 32, s, 7, k_rrc_int, 0); + + err = LIBLTE_SUCCESS; + } + + return (err); +} + +LIBLTE_ERROR_ENUM liblte_security_generate_k_nr_up(uint8* k_gnb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + uint8* k_up_enc, + uint8* k_up_int) +{ + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 s[7]; + + if (k_gnb != NULL && k_up_enc != NULL && k_up_int != NULL) { + // Construct S for KUPenc + s[0] = 0x69; // FC + s[1] = 0x05; // 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 KUPenc + sha256(k_gnb, 32, s, 7, k_up_enc, 0); + + // Construct S for KUPint + s[0] = 0x69; // FC + s[1] = 0x06; // P0 + s[2] = 0x00; // First byte of L0 + s[3] = 0x01; // Second byte of L0 + s[4] = int_alg_id; // P1 + s[5] = 0x00; // First byte of L1 + s[6] = 0x01; // Second byte of L1 + + // Derive KUPint + sha256(k_gnb, 32, s, 7, k_up_int, 0); + + err = LIBLTE_SUCCESS; + } + + return (err); +} + +/********************************************************************* + Name: liblte_security_generate_sk_gnb + + Description: Derivation of S-KeNB or S-KgNB for dual connectivity. + + Document Reference: 33.401 v10.0.0 Annex A.15 +*********************************************************************/ + +LIBLTE_ERROR_ENUM liblte_security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_counter) +{ + + LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS; + uint8 s[5]; + + if (k_enb != NULL && sk_gnb != NULL) { + // Construct S for sk_gnb + s[0] = 0x1C; // FC + s[1] = (scg_counter >> 8) & 0xFF; // first byte of P0 + s[2] = scg_counter & 0xFF; // second byte of P0 + s[3] = 0x00; // First byte of L0 + s[4] = 0x02; // Second byte of L0 + + // Derive sk_gnb + sha256(k_enb, 32, s, 5, sk_gnb, 0); + err = LIBLTE_SUCCESS; + } + + return (err); +} /********************************************************************* Name: liblte_security_generate_k_up diff --git a/lib/src/common/security.cc b/lib/src/common/security.cc index 8be620ba2..16ce13669 100644 --- a/lib/src/common/security.cc +++ b/lib/src/common/security.cc @@ -93,6 +93,37 @@ uint8_t security_generate_k_up(uint8_t* k_enb, k_up_int); } +uint8_t security_generate_k_nr_rrc(uint8_t* k_gnb, + CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + 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); +} + +uint8_t security_generate_k_nr_up(uint8_t* k_gnb, + CIPHERING_ALGORITHM_ID_ENUM enc_alg_id, + INTEGRITY_ALGORITHM_ID_ENUM int_alg_id, + 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); +} + +uint8_t security_generate_sk_gnb(uint8_t* k_enb, uint8_t* sk_gnb, uint16_t scg_count) +{ + return liblte_security_generate_sk_gnb(k_enb, sk_gnb, scg_count); +} + /****************************************************************************** * Integrity Protection *****************************************************************************/ diff --git a/lib/test/common/test_f12345.cc b/lib/test/common/test_f12345.cc index 54102656a..4a51211e8 100644 --- a/lib/test/common/test_f12345.cc +++ b/lib/test/common/test_f12345.cc @@ -153,6 +153,73 @@ int test_set_2() ; } +int test_set_ksg() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t k_enb[] = {0xfe, 0x7d, 0xee, 0x80, 0x8d, 0x7f, 0x3b, 0x88, 0x2a, 0x08, 0x2c, 0xbd, 0xc8, 0x39, 0x0d, 0x12, + 0x9e, 0x5d, 0x28, 0xaf, 0x0e, 0x83, 0x22, 0xeb, 0x57, 0x3a, 0xda, 0x36, 0xf2, 0x1a, 0x5a, 0x89}; + uint8_t sk_gnb_o[32]; + uint16_t scg_counter = 0; + err_lte = liblte_security_generate_sk_gnb(k_enb, sk_gnb_o, scg_counter); + TESTASSERT(err_lte == LIBLTE_SUCCESS); + arrprint(sk_gnb_o, sizeof(sk_gnb_o)); + uint8_t sk_gnb[] = {0x45, 0xcb, 0xc3, 0xf8, 0xa8, 0x11, 0x93, 0xfd, 0x5c, 0x52, 0x29, 0x30, 0x0d, 0x59, 0xed, 0xf8, + 0x12, 0xe9, 0x98, 0xa1, 0x15, 0xec, 0x4e, 0x0c, 0xe9, 0x03, 0xba, 0x89, 0x36, 0x7e, 0x26, 0x28}; + err_cmp = arrcmp(sk_gnb_o, sk_gnb, sizeof(sk_gnb)); + TESTASSERT(err_cmp == 0); + return SRSLTE_SUCCESS; +} + +int test_set_nr_rrc_up() +{ + LIBLTE_ERROR_ENUM err_lte = LIBLTE_ERROR_INVALID_INPUTS; + int32 err_cmp = 0; + + uint8_t sk_gnb[] = {0x45, 0xcb, 0xc3, 0xf8, 0xa8, 0x11, 0x93, 0xfd, 0x5c, 0x52, 0x29, 0x30, 0x0d, 0x59, 0xed, 0xf8, + 0x12, 0xe9, 0x98, 0xa1, 0x15, 0xec, 0x4e, 0x0c, 0xe9, 0x03, 0xba, 0x89, 0x36, 0x7e, 0x26, 0x28}; + + uint8_t sk_gnb_o[32]; + uint8_t k_rrc_enc_o[32]; + uint8_t k_rrc_int_o[32]; + + err_lte = liblte_security_generate_k_nr_rrc(sk_gnb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_128_EEA2, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_EIA0, + k_rrc_enc_o, + k_rrc_int_o); + + TESTASSERT(err_lte == LIBLTE_SUCCESS); + printf("RRC ENC output:\n"); + arrprint(&k_rrc_enc_o[0], sizeof(k_rrc_enc_o)); + uint8_t k_rrc_enc[] = {0x52, 0xa9, 0x95, 0xdf, 0xf8, 0x9b, 0xc2, 0x94, 0xbd, 0x89, 0xff, + 0xb1, 0x37, 0xa2, 0x9f, 0x24, 0x66, 0xa0, 0x9e, 0x99, 0x23, 0x86, + 0xc8, 0xd1, 0xdf, 0x78, 0x92, 0x96, 0x4c, 0x6f, 0xb5, 0x22}; + + err_cmp = arrcmp(k_rrc_enc_o, k_rrc_enc, sizeof(k_rrc_enc_o)); + + TESTASSERT(err_cmp == 0); + + uint8_t k_up_enc_o[32]; + uint8_t k_up_int_o[32]; + + err_lte = liblte_security_generate_k_nr_up(sk_gnb, + LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_128_EEA2, + LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_EIA0, + k_up_enc_o, + k_up_int_o); + + uint8_t k_up_enc[] = {0x7c, 0xe2, 0x06, 0x70, 0xbb, 0xbc, 0xc5, 0x90, 0x40, 0x87, 0xc0, 0xd4, 0x26, 0x53, 0xc5, 0x40, + 0x15, 0x20, 0x52, 0xd3, 0xdf, 0xbc, 0x3f, 0x05, 0x86, 0x9b, 0x7f, 0x92, 0x00, 0x95, 0xbe, 0x68}; + printf("UP ENC output:\n"); + arrprint(&k_up_enc_o[0], sizeof(k_up_enc_o)); + + err_cmp = arrcmp(k_up_enc_o, k_up_enc, sizeof(k_up_enc_o)); + TESTASSERT(err_cmp == 0); + return SRSLTE_SUCCESS; +} + /* Own test sets */ @@ -161,5 +228,7 @@ int main(int argc, char* argv[]) { TESTASSERT(test_set_2() == SRSLTE_SUCCESS); + TESTASSERT(test_set_ksg() == SRSLTE_SUCCESS); + TESTASSERT(test_set_nr_rrc_up() == SRSLTE_SUCCESS); return SRSLTE_SUCCESS; }