Merge remote-tracking branch 'origin/merge_secu_osa' into integration_2023_w21

This commit is contained in:
Robert Schmidt
2023-05-26 16:48:10 +02:00
53 changed files with 832 additions and 1778 deletions
-2
View File
@@ -23,8 +23,6 @@
#include "commonDef.h"
#include "security_types.h"
#include "queue.h"
#ifndef COMMON_TYPES_H_
-44
View File
@@ -42,14 +42,6 @@
#define AUTN_LENGTH_BITS (128)
#define AUTN_LENGTH_OCTETS (AUTN_LENGTH_BITS/8)
/* Some methods to convert a string to an int64_t */
/*
#define STRING_TO_64BITS(sTRING, cONTAINER) \
sscanf(sTRING, "%" SCN64, cONTAINER)
#define STRING_TO_U64BITS(sTRING, cONTAINER) \
sscanf(sTRING, "%" SCNu64, cONTAINER)
*/
/* Converts a string to 128 bits gmplib integer holder */
# define STRING_TO_XBITS(sTRING, lENGTH, cONTAINER, rET) \
do { \
@@ -63,18 +55,6 @@ STRING_TO_XBITS(sTRING, 16, cONTAINER, rET)
# define STRING_TO_256BITS(sTRING, cONTAINER, rET) \
STRING_TO_XBITS(sTRING, 32, cONTAINER, rET)
# define STRING_TO_RAND STRING_TO_128BITS
# define STRING_TO_AUTH_KEY STRING_TO_128BITS
# define STRING_TO_AUTH_RES STRING_TO_128BITS
# define STRING_TO_AUTN STRING_TO_128BITS
# define STRING_TO_KASME STRING_TO_256BITS
# define STRING_TO_XRES(sTRING, lENGTH, cONTAINER, rET) \
do { \
STRING_TO_XBITS(sTRING, lENGTH, (cONTAINER)->data, rET); \
if (rET != -1) \
(cONTAINER)->size = lENGTH; \
} while(0)
/* RES amd XRES can have a variable length of 4-16 octets */
typedef struct {
uint8_t size;
@@ -107,28 +87,4 @@ typedef struct eutran_vector_s {
uint8_t kasme[KASME_LENGTH_OCTETS];
} eutran_vector_t;
#define FC_KASME (0x10)
#define FC_KENB (0x11)
#define FC_NH (0x12)
#define FC_KENB_STAR (0x13)
/* 33401 #A.7 Algorithm for key derivation function.
* This FC should be used for:
* - NAS Encryption algorithm
* - NAS Integrity algorithm
* - RRC Encryption algorithm
* - RRC Integrity algorithm
* - User Plane Encryption algorithm
*/
#define FC_ALG_KEY_DER (0x15)
#define FC_KASME_TO_CK (0x16)
typedef enum {
NAS_ENC_ALG = 0x01,
NAS_INT_ALG = 0x02,
RRC_ENC_ALG = 0x03,
RRC_INT_ALG = 0x04,
UP_ENC_ALG = 0x05,
UP_INT_ALG = 0x06
} algorithm_type_dist_t;
#endif /* SECURITY_TYPES_H_ */
+8 -13
View File
@@ -53,8 +53,6 @@ Description Defines the layer 3 messages supported by the NAS sublayer
#include "secu_defs.h"
#include "emmData.h"
//#define DEBUG_NAS_MESSAGE
/****************************************************************************/
/**************** E X T E R N A L D E F I N I T I O N S ****************/
/****************************************************************************/
@@ -1019,7 +1017,8 @@ static int _nas_message_decrypt(
stream_cipher.message = (unsigned char *)src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea1(&stream_cipher, (unsigned char *)dest);
stream_compute_encrypt(EEA1_128_ALG_ID, &stream_cipher, (unsigned char *)dest);
/* Decode the first octet (security header type or EPS bearer identity,
* and protocol discriminator) */
DECODE_U8(dest, *(uint8_t*)(&header), size);
@@ -1054,7 +1053,8 @@ static int _nas_message_decrypt(
stream_cipher.message = (unsigned char *)src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea1(&stream_cipher, (unsigned char *)dest);
stream_compute_encrypt(EEA1_128_ALG_ID, &stream_cipher, (unsigned char *)dest);
/* Decode the first octet (security header type or EPS bearer identity,
* and protocol discriminator) */
DECODE_U8(dest, *(uint8_t*)(&header), size);
@@ -1186,8 +1186,7 @@ static int _nas_message_encrypt(
stream_cipher.message = (unsigned char *)src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea1(&stream_cipher, (unsigned char *)dest);
stream_compute_encrypt(EEA1_128_ALG_ID, &stream_cipher, (unsigned char *)dest);
LOG_FUNC_RETURN (length);
}
@@ -1217,7 +1216,7 @@ static int _nas_message_encrypt(
stream_cipher.message = (unsigned char *)src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea2(&stream_cipher, (unsigned char *)dest);
stream_compute_encrypt(EEA2_128_ALG_ID, &stream_cipher, (unsigned char *)dest);
LOG_FUNC_RETURN (length);
@@ -1356,10 +1355,8 @@ static uint32_t _nas_message_get_mac(
stream_cipher.message = (unsigned char *)buffer;
/* length in bits */
stream_cipher.blength = length << 3;
stream_compute_integrity(EIA1_128_ALG_ID, &stream_cipher, mac);
nas_stream_encrypt_eia1(
&stream_cipher,
mac);
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EIA1 returned MAC %x.%x.%x.%x(%u) for length %d direction %d, count %d",
mac[0], mac[1], mac[2],mac[3],
@@ -1402,10 +1399,8 @@ static uint32_t _nas_message_get_mac(
stream_cipher.message = (unsigned char *)buffer;
/* length in bits */
stream_cipher.blength = length << 3;
stream_compute_integrity(EIA2_128_ALG_ID, &stream_cipher, mac);
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EIA2 returned MAC %x.%x.%x.%x(%u) for length %d direction %d, count %d",
mac[0], mac[1], mac[2],mac[3],
+61 -36
View File
@@ -29,10 +29,11 @@
#ifndef MILENAGE_H
#define MILENAGE_H
#include <openssl/aes.h>
#include "openair3/SECU/aes_128_ecb.h"
#define u8 uint8_t
/**
milenage_f1 - Milenage f1 and f1* algorithms
@opc: OPc = 128-bit value derived from OP and K
@@ -45,16 +46,29 @@
Returns: true on success, false on failure
*/
void aes_128_encrypt_block(const u8* key, const u8* in, u8* out) {
AES_KEY k;
u8 tmp[16];
AES_set_encrypt_key(key, 128, &k);
AES_encrypt(in, tmp, &k);
void aes_128_encrypt_block(const uint8_t *key, const uint8_t *in, uint8_t *out)
{
abort();
assert(0 != 0 && "Here we are!");
// Precondition: key, in and out occupy 16 bytes
aes_128_t k_iv = {.type = NONE_INITIALIZATION_VECTOR};
memcpy(k_iv.key, key, sizeof(k_iv.key));
byte_array_t msg = {.buf = (uint8_t *)in, .len = 16};
uint8_t tmp[16] = {0};
aes_128_ecb(&k_iv, msg, sizeof(tmp), tmp);
memcpy(out, tmp, sizeof(tmp));
}
static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s) {
u8 tmp1[16], tmp2[16], tmp3[16];
static bool milenage_f1(const uint8_t *opc,
const uint8_t *k,
const uint8_t *_rand,
const uint8_t *sqn,
const uint8_t *amf,
uint8_t *mac_a,
uint8_t *mac_s)
{
uint8_t tmp1[16], tmp2[16], tmp3[16];
int i;
/* tmp1 = TEMP = E_K(RAND XOR OP_C) */
@@ -62,10 +76,10 @@ static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
tmp1[i] = _rand[i] ^ opc[i];
aes_128_encrypt_block(k, tmp1, tmp1);
AES_KEY kTab;
uint8_t cyphered[16];
AES_set_encrypt_key(k, 128, &kTab);
AES_encrypt(tmp1, cyphered, &kTab);
uint8_t cyphered[16] = {0};
aes_128_encrypt_block(k, tmp1, cyphered);
/* tmp2 = IN1 = SQN || AMF || SQN || AMF */
memcpy(tmp2, sqn, 6);
memcpy(tmp2 + 6, amf, 2);
@@ -97,7 +111,6 @@ static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
return true;
}
/**
milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms
@opc: OPc = 128-bit value derived from OP and K
@@ -110,9 +123,16 @@ static bool milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
@akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL
Returns: true on success, false on failure
*/
static bool milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar) {
u8 tmp1[16], tmp2[16], tmp3[16];
static bool milenage_f2345(const uint8_t *opc,
const uint8_t *k,
const uint8_t *_rand,
uint8_t *res,
uint8_t *ck,
uint8_t *ik,
uint8_t *ak,
uint8_t *akstar)
{
uint8_t tmp1[16], tmp2[16], tmp3[16];
int i;
/* tmp2 = TEMP = E_K(RAND XOR OP_C) */
@@ -186,7 +206,6 @@ static bool milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
return true;
}
/**
milenage_generate - Generate AKA AUTN,IK,CK,RES
@opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
@@ -200,11 +219,18 @@ static bool milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
@res: Buffer for RES = 64-bit signed response (f2), or %NULL
@res_len: Max length for res; set to used length or 0 on failure
*/
static bool milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik,
u8 *ck, u8 *res) {
static bool milenage_generate(const uint8_t *opc,
const uint8_t *amf,
const uint8_t *k,
const uint8_t *sqn,
const uint8_t *_rand,
uint8_t *autn,
uint8_t *ik,
uint8_t *ck,
uint8_t *res)
{
int i;
u8 mac_a[8], ak[6];
uint8_t mac_a[8], ak[6];
if (!milenage_f1(opc, k, _rand, sqn, amf, mac_a, NULL) ||
!milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
@@ -219,7 +245,6 @@ static bool milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
return true;
}
/**
milenage_auts - Milenage AUTS validation
@opc: OPc = 128-bit operator variant algorithm configuration field (encr.)
@@ -232,10 +257,10 @@ static bool milenage_generate(const u8 *opc, const u8 *amf, const u8 *k,
#define p(a) printf("%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", (int)((a)[0]), (int)((a)[1]), (int)((a)[2]), (int)((a)[3]),(int)((a)[4]), (int)((a)[5]));
// valid code but put in comment as it is not used right now
#if 0
static bool milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts,
u8 *sqn) {
u8 amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
u8 ak[6], mac_s[8];
static bool milenage_auts(const uint8_t *opc, const uint8_t *k, const uint8_t *_rand, const uint8_t *auts,
uint8_t *sqn) {
uint8_t amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
uint8_t ak[6], mac_s[8];
int i;
if (!milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
@@ -262,8 +287,8 @@ static bool milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8
@kc: Buffer for Kc = 64-bit Kc
Returns: 0 on success, -1 on failure
*/
static bool gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, u8 *kc) {
u8 res[8], ck[16], ik[16];
static bool gsm_milenage(const uint8_t *opc, const uint8_t *k, const uint8_t *_rand, uint8_t *sres, uint8_t *kc) {
uint8_t res[8], ck[16], ik[16];
int i;
if (milenage_f2345(opc, k, _rand, res, ck, ik, NULL, NULL))
@@ -298,12 +323,12 @@ static bool gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres,
@auts: 112-bit buffer for AUTS
Returns: 0 on success, -1 on failure, or -2 on synchronization failure
*/
static int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand,
const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len,
u8 *auts) {
static int milenage_check(const uint8_t *opc, const uint8_t *k, const uint8_t *sqn, const uint8_t *_rand,
const uint8_t *autn, uint8_t *ik, uint8_t *ck, uint8_t *res, size_t *res_len,
uint8_t *auts) {
int i;
u8 mac_a[8], ak[6], rx_sqn[6];
const u8 *amf;
uint8_t mac_a[8], ak[6], rx_sqn[6];
const uint8_t *amf;
if (milenage_f2345(opc, k, _rand, res, ck, ik, ak, NULL))
return -1;
@@ -315,7 +340,7 @@ static int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_
rx_sqn[i] = autn[i] ^ ak[i];
if (memcmp(rx_sqn, sqn, 6) <= 0) {
u8 auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
uint8_t auts_amf[2] = { 0x00, 0x00 }; /* TS 33.102 v7.0.0, 6.3.3 */
if (milenage_f2345(opc, k, _rand, NULL, NULL, NULL, NULL, ak))
return -1;
@@ -342,7 +367,7 @@ static int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_
return 0;
}
static void milenage_opc_gen(const u8 *k, const u8 *op, u8 *opc) {
static void milenage_opc_gen(const uint8_t *k, const uint8_t *op, uint8_t *opc) {
int i;
/* Encrypt OP using K */
aes_128_encrypt_block(k, op, opc);
+5 -9
View File
@@ -40,6 +40,7 @@
#include "aka_functions.h"
#include "secu_defs.h"
#include "kdf.h"
#include "key_nas_deriver.h"
#include "PduSessionEstablishRequest.h"
#include "PduSessionEstablishmentAccept.h"
#include "RegistrationAccept.h"
@@ -50,6 +51,7 @@
#include <openair1/PHY/phy_extern_nr_ue.h>
#include <openair1/SIMULATION/ETH_TRANSPORT/proto.h>
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
#include "openair3/SECU/nas_stream_eia2.h"
uint8_t *registration_request_buf;
uint32_t registration_request_len;
@@ -597,9 +599,7 @@ static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initia
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
stream_compute_integrity(EIA2_128_ALG_ID, &stream_cipher, mac);
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
@@ -702,9 +702,7 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas, as_nas_info_t *initia
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
stream_compute_integrity(EIA2_128_ALG_ID, &stream_cipher, mac);
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
@@ -861,9 +859,7 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *
stream_cipher.blength = (initialNasMsg->length - 6) << 3;
// only for Type of integrity protection algorithm: 128-5G-IA2 (2)
nas_stream_encrypt_eia2(
&stream_cipher,
mac);
stream_compute_integrity(EIA2_128_ALG_ID, &stream_cipher, mac);
printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]);
for(int i = 0; i < 4; i++){
+2 -1
View File
@@ -62,9 +62,10 @@ typedef struct{
};
} iv8_t;
typedef enum{
typedef enum {
AES_INITIALIZATION_VECTOR_8,
AES_INITIALIZATION_VECTOR_16,
NONE_INITIALIZATION_VECTOR,
AES_INITIALIZATION_VECTOR_END,
} iv_e;
+53
View File
@@ -0,0 +1,53 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "aes_128_ecb.h"
#include "common/utils/assertions.h"
#include <openssl/aes.h>
#include <openssl/err.h>
#include <openssl/evp.h>
void aes_128_ecb(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out])
{
DevAssert(k_iv != NULL);
DevAssert(k_iv->type == NONE_INITIALIZATION_VECTOR);
// Create and initialise the context
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
DevAssert(ctx != NULL);
// Initialise the encryption operation.
int rc = EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, k_iv->key, NULL);
DevAssert(rc == 1);
int len_ev = 0;
rc = EVP_EncryptUpdate(ctx, out, &len_ev, msg.buf, msg.len);
DevAssert(!(len_ev > len_out) && "Buffer overflow");
// Finalise the encryption. Normally ciphertext bytes may be written at
// this stage, but this does not occur in GCM mode
rc = EVP_EncryptFinal_ex(ctx, out + len_ev, &len_ev);
DevAssert(rc == 1);
// Get the tag
// rc == EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag))
EVP_CIPHER_CTX_free(ctx);
}
+30
View File
@@ -0,0 +1,30 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef AES_128_ECB_OAI_H
#define AES_128_ECB_OAI_H
#include "aes_128.h"
#include "common/utils/ds/byte_array.h"
void aes_128_ecb(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out]);
#endif
+202 -40
View File
@@ -19,16 +19,84 @@
* contact@openairinterface.org
*/
#include "aes_128.h"
#include "aes_128_cbc_cmac.h"
#include "common/utils/assertions.h"
#include "common/utils/LOG/log.h"
#include "kdf.h"
#include "key_nas_deriver.h"
#include "nas_stream_eea1.h"
#include "nas_stream_eea2.h"
#include "nas_stream_eia1.h"
#include "nas_stream_eia2.h"
#include "secu_defs.h"
#include "snow3g.h"
#include <arpa/inet.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "security_types.h"
#include "secu_defs.h"
#include "kdf.h"
#define FC_KENB (0x11)
#define FC_NH (0x12)
#define FC_KENB_STAR (0x13)
/* 33401 #A.7 Algorithm for key derivation function.
* This FC should be used for:
* - NAS Encryption algorithm
* - NAS Integrity algorithm
* - RRC Encryption algorithm
* - RRC Integrity algorithm
* - User Plane Encryption algorithm
*/
#define FC_ALG_KEY_DER (0x15)
#define FC_KASME_TO_CK (0x16)
#define NR_FC_ALG_KEY_DER (0x69)
#define NR_FC_ALG_KEY_NG_RAN_STAR_DER (0x70)
// #define SECU_DEBUG 1
static void derive_key_common(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t kasme[32], uint8_t FC, uint8_t out[32])
{
uint8_t s[7];
#if defined(SECU_DEBUG)
int i;
#endif
/* FC */
s[0] = FC;
/* P0 = algorithm type distinguisher */
s[1] = (uint8_t)(alg_type & 0xFF);
/* L0 = length(P0) = 1 */
s[2] = 0x00;
s[3] = 0x01;
/* P1 */
s[4] = alg_id;
/* L1 = length(P1) = 1 */
s[5] = 0x00;
s[6] = 0x01;
#if defined(SECU_DEBUG)
printf("%s FC %d nas_alg_type distinguisher %d nas_enc_alg_identity %d\n", __FUNCTION__, FC_ALG_KEY_DER, alg_type, alg_id);
for (i = 0; i < 7; i ++) {
printf("0x%02x ", s[i]);
}
printf("\n");
#endif
byte_array_t data = {.len = 7, .buf = s};
kdf(kasme, data, 32, out);
}
#define SECU_DEBUG 1
/*!
* @brief Derive the kNASenc from kasme and perform truncate on the generated key to
* reduce his size to 128 bits. Definition of the derivation function can
@@ -41,50 +109,144 @@
* - 2 for 128-EIA2 AES
* @param[in] kasme Key for MME as provided by AUC
* @param[out] knas Pointer to reference where output of KDF will be stored.
*/
void derive_key_nas(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t kasme[32], uint8_t knas[32])
{
derive_key_common(alg_type, alg_id, kasme, FC_ALG_KEY_DER, knas);
}
void nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16])
{
uint8_t tmp[32] = {0};
derive_key_common(alg_type, alg_id, key, NR_FC_ALG_KEY_DER, tmp);
// Only the last 16 bytes are needed in 5G
memcpy(out, &tmp[16], 16);
}
/*!
* @brief Derive the keys from key and perform truncate on the generated key to
* reduce his size to 128 bits. Definition of the derivation function can
* be found in 3GPP TS.33401 #A.7
* @param[in] alg_type Algorithm distinguisher
* @param[in] alg_id Algorithm identifier.
* Possible values are:
* - 0 for EIA0 algorithm (Null Integrity Protection algorithm)
* - 1 for 128-EIA1 SNOW 3G
* - 2 for 128-EIA2 AES
* @param[in] key The top key used to derive other subkeys
* @param[out] out Pointer to reference where output of KDF will be stored.
* NOTE: knas is dynamically allocated by the KDF function
*/
int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
const uint8_t kasme[32], uint8_t *knas)
#ifndef NAS_UE
void derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB)
{
uint8_t s[7];
uint8_t out[32];
#if defined(SECU_DEBUG)
int i;
uint8_t s[7] = {0};
// FC
s[0] = FC_KENB;
// P0 = Uplink NAS count
s[1] = (nas_count & 0xff000000) >> 24;
s[2] = (nas_count & 0x00ff0000) >> 16;
s[3] = (nas_count & 0x0000ff00) >> 8;
s[4] = (nas_count & 0x000000ff);
// Length of NAS count
s[5] = 0x00;
s[6] = 0x04;
byte_array_t data = {.buf = s, .len = 7};
kdf(kasme, data, 32, keNB);
}
#endif
/* FC */
s[0] = FC_ALG_KEY_DER;
/* P0 = algorithm type distinguisher */
s[1] = (uint8_t)(nas_alg_type & 0xFF);
/* L0 = length(P0) = 1 */
s[2] = 0x00;
s[3] = 0x01;
/* P1 */
s[4] = nas_enc_alg_id;
/* L1 = length(P1) = 1 */
s[5] = 0x00;
s[6] = 0x01;
#if defined(SECU_DEBUG)
printf("%s FC %d nas_alg_type distinguisher %d nas_enc_alg_identity %d\n",
__FUNCTION__, FC_ALG_KEY_DER, nas_alg_type, nas_enc_alg_id);
for (i = 0; i < 7; i ++) {
printf("0x%02x ", s[i]);
void derive_keNB_star(const uint8_t *kenb_32,
const uint16_t pci,
const uint32_t earfcn_dl,
const bool is_rel8_only,
uint8_t *kenb_star)
{
// see 33.401 section A.5 KeNB* derivation function
uint8_t s[10] = {0};
byte_array_t data = {.buf = s};
// FC = 0x13
s[0] = FC_KENB_STAR;
// P0 = PCI (target physical cell id)
s[1] = (pci & 0x0000ff00) >> 8;
s[2] = (pci & 0x000000ff);
// L0 = length of PCI (i.e. 0x00 0x02)
s[3] = 0x00;
s[4] = 0x02;
// P1 = EARFCN-DL (target physical cell downlink frequency)
if (is_rel8_only) {
s[5] = (earfcn_dl & 0x0000ff00) >> 8;
s[6] = (earfcn_dl & 0x000000ff);
s[7] = 0x00;
s[8] = 0x02;
data.len = 9;
} else {
s[5] = (earfcn_dl & 0x00ff0000) >> 16;
s[6] = (earfcn_dl & 0x0000ff00) >> 8;
s[7] = (earfcn_dl & 0x000000ff);
s[8] = 0x00;
s[9] = 0x03;
data.len = 10;
}
printf("\n");
#endif
kdf(kenb_32, data, 32, kenb_star);
//kdf(kasme, 32, s, 7, out, 32);
byte_array_t data = {.len = 7, .buf = s};
kdf(kasme, data, 32, out);
// L1 length of EARFCN-DL (i.e. L1 = 0x00 0x02 if EARFCN-DL is between 0 and 65535, and L1 = 0x00 0x03 if EARFCN-DL is between
// 65536 and 262143) NOTE: The length of EARFCN-DL cannot be generally set to 3 bytes for backward compatibility reasons: A Rel-8
// entity (UE or eNB) would always assume an input parameter length of 2 bytes for the EARFCN-DL. This
// would lead to different derived keys if another entity assumed an input parameter length of 3 bytes for the
// EARFCN-DL.
}
memcpy(knas, &out[31-16+1], 16);
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star)
{
uint8_t s[10] = {0};
return 0;
/* FC */
s[0] = NR_FC_ALG_KEY_NG_RAN_STAR_DER;
/* P0 = PCI */
s[1] = (pci & 0x0000ff00) >> 8;
s[2] = (pci & 0x000000ff);
/* L0 = length(P0) = 2 */
s[3] = 0x00;
s[4] = 0x02;
/* P1 = NR ARFCN */
s[5] = (nr_arfcn_dl & 0x00ff0000) >> 16;
s[6] = (nr_arfcn_dl & 0x0000ff00) >> 8;
s[7] = (nr_arfcn_dl & 0x000000ff);
/* L1 = length(P1) = 3 */
s[8] = 0x00;
s[9] = 0x03;
byte_array_t data = {.buf = s, .len = 10};
const uint32_t len_key = 32;
kdf(key, data, len_key, key_ng_ran_star);
}
void derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB)
{
uint8_t s[5] = {0};
/* FC is 0x1c (see 3gpp 33.401 annex A.15) */
s[0] = 0x1c;
/* put sk_counter */
s[1] = (sk_counter >> 8) & 0xff;
s[2] = sk_counter & 0xff;
/* put length of sk_counter (2) */
s[3] = 0x00;
s[4] = 0x02;
byte_array_t data = {.buf = s, .len = 5};
kdf(keNB, data, 32, skgNB);
}
+33
View File
@@ -0,0 +1,33 @@
#ifndef KEY_NAS_DERIVER_H
#define KEY_NAS_DERIVER_H
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
typedef enum {
NAS_ENC_ALG = 0x01,
NAS_INT_ALG = 0x02,
RRC_ENC_ALG = 0x03,
RRC_INT_ALG = 0x04,
UP_ENC_ALG = 0x05,
UP_INT_ALG = 0x06
} algorithm_type_dist_t;
void derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB);
void derive_keNB_star(const uint8_t *kenb_32,
const uint16_t pci,
const uint32_t earfcn_dl,
const bool is_rel8_only,
uint8_t *kenb_star);
void derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id, const uint8_t kasme[32], uint8_t knas[32]);
void derive_skgNB(const uint8_t *keNB, const uint16_t sk_counter, uint8_t *skgNB);
void nr_derive_key(algorithm_type_dist_t alg_type, uint8_t alg_id, const uint8_t key[32], uint8_t out[16]);
void nr_derive_key_ng_ran_star(uint16_t pci, uint64_t nr_arfcn_dl, const uint8_t key[32], uint8_t *key_ng_ran_star);
#endif
+44
View File
@@ -0,0 +1,44 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "nas_stream_eea0.h"
#include "common/utils/assertions.h"
#include "common/utils/LOG/log.h"
#include <string.h>
void nas_stream_encrypt_eea0(nas_stream_cipher_t const *stream_cipher, uint8_t *out)
{
DevAssert(stream_cipher != NULL);
DevAssert(out != NULL);
LOG_D(OSA,
"Entering stream_encrypt_eea0, bits length %u, bearer %u, "
"count %u, direction %s\n",
stream_cipher->blength,
stream_cipher->bearer,
stream_cipher->count,
stream_cipher->direction == SECU_DIRECTION_DOWNLINK ? "Downlink" : "Uplink");
uint32_t byte_length = (stream_cipher->blength + 7) >> 3;
memcpy(out, stream_cipher->message, byte_length);
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef OAI_NAS_STREAM_EEA0_H
#define OAI_NAS_STREAM_EEA0_H
#include "secu_defs.h"
#include <stdlib.h>
#include <stdint.h>
void nas_stream_encrypt_eea0(nas_stream_cipher_t const *stream_cipher, uint8_t *out);
#endif
+2 -7
View File
@@ -26,13 +26,10 @@
#include "assertions.h"
#include "conversions.h"
#include "secu_defs.h"
#include "nas_stream_eea1.h"
#include "snow3g.h"
// #define SECU_DEBUG
int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t *out)
void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t *out)
{
snow_3g_context_t snow_3g_context;
int n ;
@@ -106,6 +103,4 @@ int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t *out)
if (zero_bit > 0) {
out[ceil_index - 1] = stream_cipher->message[ceil_index - 1];
}
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef OAI_NAS_STREAM_EEA1_H
#define OAI_NAS_STREAM_EEA1_H
#include "secu_defs.h"
#include <stdlib.h>
#include <stdint.h>
void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t *out);
#endif
+2 -4
View File
@@ -28,9 +28,9 @@
#include "aes_128_ctr.h"
#include "assertions.h"
#include "conversions.h"
#include "secu_defs.h"
#include "nas_stream_eea2.h"
int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t *out)
void nas_stream_encrypt_eea2(nas_stream_cipher_t const *stream_cipher, uint8_t *out)
{
DevAssert(stream_cipher != NULL);
DevAssert(stream_cipher->key != NULL);
@@ -53,6 +53,4 @@ int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t *out)
const size_t len_out = byte_lenght;
byte_array_t msg = {.buf = stream_cipher->message, .len = byte_lenght};
aes_128_ctr(&p, msg, len_out, out);
return 0;
}
+65
View File
@@ -0,0 +1,65 @@
/*
* 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_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] = {
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D,
0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB,
0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D,
0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9,
0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16};
/* S-box OSA_SQ */
static const uint8_t OSA_SQ[256] = {
0x25, 0x24, 0x73, 0x67, 0xD7, 0xAE, 0x5C, 0x30, 0xA4, 0xEE, 0x6E, 0xCB, 0x7D, 0xB5, 0x82, 0xDB, 0xE4, 0x8E, 0x48, 0x49,
0x4F, 0x5D, 0x6A, 0x78, 0x70, 0x88, 0xE8, 0x5F, 0x5E, 0x84, 0x65, 0xE2, 0xD8, 0xE9, 0xCC, 0xED, 0x40, 0x2F, 0x11, 0x28,
0x57, 0xD2, 0xAC, 0xE3, 0x4A, 0x15, 0x1B, 0xB9, 0xB2, 0x80, 0x85, 0xA6, 0x2E, 0x02, 0x47, 0x29, 0x07, 0x4B, 0x0E, 0xC1,
0x51, 0xAA, 0x89, 0xD4, 0xCA, 0x01, 0x46, 0xB3, 0xEF, 0xDD, 0x44, 0x7B, 0xC2, 0x7F, 0xBE, 0xC3, 0x9F, 0x20, 0x4C, 0x64,
0x83, 0xA2, 0x68, 0x42, 0x13, 0xB4, 0x41, 0xCD, 0xBA, 0xC6, 0xBB, 0x6D, 0x4D, 0x71, 0x21, 0xF4, 0x8D, 0xB0, 0xE5, 0x93,
0xFE, 0x8F, 0xE6, 0xCF, 0x43, 0x45, 0x31, 0x22, 0x37, 0x36, 0x96, 0xFA, 0xBC, 0x0F, 0x08, 0x52, 0x1D, 0x55, 0x1A, 0xC5,
0x4E, 0x23, 0x69, 0x7A, 0x92, 0xFF, 0x5B, 0x5A, 0xEB, 0x9A, 0x1C, 0xA9, 0xD1, 0x7E, 0x0D, 0xFC, 0x50, 0x8A, 0xB6, 0x62,
0xF5, 0x0A, 0xF8, 0xDC, 0x03, 0x3C, 0x0C, 0x39, 0xF1, 0xB8, 0xF3, 0x3D, 0xF2, 0xD5, 0x97, 0x66, 0x81, 0x32, 0xA0, 0x00,
0x06, 0xCE, 0xF6, 0xEA, 0xB7, 0x17, 0xF7, 0x8C, 0x79, 0xD6, 0xA7, 0xBF, 0x8B, 0x3F, 0x1F, 0x53, 0x63, 0x75, 0x35, 0x2C,
0x60, 0xFD, 0x27, 0xD3, 0x94, 0xA5, 0x7C, 0xA1, 0x05, 0x58, 0x2D, 0xBD, 0xD9, 0xC7, 0xAF, 0x6B, 0x54, 0x0B, 0xE0, 0x38,
0x04, 0xC8, 0x9D, 0xE7, 0x14, 0xB1, 0x87, 0x9C, 0xDF, 0x6F, 0xF9, 0xDA, 0x2A, 0xC4, 0x59, 0x16, 0x74, 0x91, 0xAB, 0x26,
0x61, 0x76, 0x34, 0x2B, 0xAD, 0x99, 0xFB, 0x72, 0xEC, 0x33, 0x12, 0xDE, 0x98, 0x3B, 0xC0, 0x9B, 0x3E, 0x18, 0x10, 0x3A,
0x56, 0xE1, 0x77, 0xC9, 0x1E, 0x9E, 0x95, 0xA3, 0x90, 0x19, 0xA8, 0x6C, 0x09, 0xD0, 0xF0, 0x86};
void nas_stream_encrypt_eea2(nas_stream_cipher_t const *stream_cipher, uint8_t *out);
#endif
+6 -13
View File
@@ -25,7 +25,7 @@
#include <string.h>
#include <math.h> // double ceil(double x);
#include "secu_defs.h"
#include "nas_stream_eia1.h"
#include "assertions.h"
#include "conversions.h"
@@ -33,12 +33,6 @@
#define SECU_DEBUG
uint64_t MUL64x(uint64_t V, uint64_t c);
uint64_t MUL64xPOW(uint64_t V, uint32_t i, uint64_t c);
uint64_t MUL64(uint64_t V, uint64_t P, uint64_t c);
int nas_stream_encrypt_eia1(nas_stream_cipher_t *stream_cipher, uint8_t out[4]);
// see spec 3GPP Confidentiality and Integrity Algorithms UEA2&UIA2. Document 1: UEA2 and UIA2 Specification. Version 1.1
/* MUL64x.
@@ -49,7 +43,7 @@ int nas_stream_encrypt_eia1(nas_stream_cipher_t *stream_cipher, uint8_t out
* function.
* See section 4.3.2 for details.
*/
uint64_t MUL64x(uint64_t V, uint64_t c)
static uint64_t MUL64x(uint64_t V, uint64_t c)
{
if ( V & 0x8000000000000000 )
return (V << 1) ^ c;
@@ -65,7 +59,7 @@ uint64_t MUL64x(uint64_t V, uint64_t c)
function.
* See section 4.3.3 for details.
*/
uint64_t MUL64xPOW(uint64_t V, uint32_t i, uint64_t c)
static uint64_t MUL64xPOW(uint64_t V, uint32_t i, uint64_t c)
{
if ( i == 0)
return V;
@@ -81,7 +75,7 @@ uint64_t MUL64xPOW(uint64_t V, uint32_t i, uint64_t c)
* function.
* See section 4.3.4 for details.
*/
uint64_t MUL64(uint64_t V, uint64_t P, uint64_t c)
static uint64_t MUL64(uint64_t V, uint64_t P, uint64_t c)
{
uint64_t result = 0;
int i = 0;
@@ -99,7 +93,7 @@ uint64_t MUL64(uint64_t V, uint64_t P, uint64_t c)
* Output : a 32 bit mask.
* Prepares a 32 bit mask with required number of 1 bits on the MSB side.
*/
uint32_t mask32bit(int n)
static uint32_t mask32bit(int n)
{
uint32_t mask=0x0;
@@ -118,7 +112,7 @@ uint32_t mask32bit(int n)
* @param[in] stream_cipher Structure containing various variables to setup encoding
* @param[out] out For EIA1 the output string is 32 bits long
*/
int nas_stream_encrypt_eia1(nas_stream_cipher_t *stream_cipher, uint8_t out[4])
void nas_stream_encrypt_eia1(nas_stream_cipher_t const *stream_cipher, uint8_t out[4])
{
snow_3g_context_t snow_3g_context;
uint32_t K[4],IV[4], z[5];
@@ -218,5 +212,4 @@ int nas_stream_encrypt_eia1(nas_stream_cipher_t *stream_cipher, uint8_t out[4])
//printf ("MAC_I:%16X\n",MAC_I);
MAC_I = hton_int32(MAC_I);
memcpy(out, &MAC_I, 4);
return 0;
}
+29
View File
@@ -0,0 +1,29 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef OAI_NAS_STREAM_EIA1_H
#define OAI_NAS_STREAM_EIA1_H
#include "secu_defs.h"
void nas_stream_encrypt_eia1(nas_stream_cipher_t const* stream_cipher, uint8_t out[4]);
#endif
+4 -5
View File
@@ -25,7 +25,7 @@
#include <stdint.h>
#include <string.h>
#include "secu_defs.h"
#include "nas_stream_eia2.h"
#include <arpa/inet.h>
#include "aes_128_cbc_cmac.h"
@@ -40,7 +40,7 @@
* @param[out] out For EIA2 the output string is 32 bits long
*/
int nas_stream_encrypt_eia2(nas_stream_cipher_t *stream_cipher, uint8_t out[4])
void nas_stream_encrypt_eia2(nas_stream_cipher_t const *stream_cipher, uint8_t out[4])
{
DevAssert(stream_cipher != NULL);
DevAssert(stream_cipher->message != NULL);
@@ -49,7 +49,7 @@ int nas_stream_encrypt_eia2(nas_stream_cipher_t *stream_cipher, uint8_t out[4])
DevAssert((stream_cipher->blength & 0x7) == 0);
aes_128_t k_iv = {0};
memcpy(&k_iv.key, stream_cipher->key, sizeof(k_iv.key));
memcpy(k_iv.key, stream_cipher->key, sizeof(k_iv.key));
k_iv.type = AES_INITIALIZATION_VECTOR_8;
k_iv.iv8.d.bearer = stream_cipher->bearer;
k_iv.iv8.d.direction = stream_cipher->direction;
@@ -59,8 +59,7 @@ int nas_stream_encrypt_eia2(nas_stream_cipher_t *stream_cipher, uint8_t out[4])
uint8_t result[16] = {0};
byte_array_t msg = {.buf = stream_cipher->message, .len = m_length };
aes_128_cbc_cmac(&k_iv, msg, sizeof(result), result);
memcpy(out, result, 4);
return 0;
}
+29
View File
@@ -0,0 +1,29 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#ifndef OAI_NAS_STREAM_EIA2_H
#define OAI_NAS_STREAM_EIA2_H
#include "secu_defs.h"
void nas_stream_encrypt_eia2(nas_stream_cipher_t const* stream_cipher, uint8_t out[4]);
#endif
+38 -68
View File
@@ -19,78 +19,48 @@
* contact@openairinterface.org
*/
#include "secu_defs.h"
#include "kdf.h"
#ifndef NAS_UE
int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB)
#include "common/utils/assertions.h"
#include "common/utils/LOG/log.h"
#include "nas_stream_eea0.h"
#include "nas_stream_eea1.h"
#include "nas_stream_eea2.h"
#include "nas_stream_eia1.h"
#include "nas_stream_eia2.h"
void stream_compute_integrity(eia_alg_id_e alg, nas_stream_cipher_t const* stream_cipher, uint8_t out[4])
{
uint8_t s[7] = {0};
// FC
s[0] = FC_KENB;
// P0 = Uplink NAS count
s[1] = (nas_count & 0xff000000) >> 24;
s[2] = (nas_count & 0x00ff0000) >> 16;
s[3] = (nas_count & 0x0000ff00) >> 8;
s[4] = (nas_count & 0x000000ff);
// Length of NAS count
s[5] = 0x00;
s[6] = 0x04;
// kdf(kasme, 32, s, 7, keNB, 32);
byte_array_t data = {.buf = s, .len = 7};
kdf(kasme, data, 32, keNB);
return 0;
}
#endif
int derive_keNB_star(
const uint8_t *kenb_32,
const uint16_t pci,
const uint32_t earfcn_dl,
const bool is_rel8_only,
uint8_t *kenb_star)
{
// see 33.401 section A.5 KeNB* derivation function
uint8_t s[10] = {0};
byte_array_t data = {.buf = s};
// FC = 0x13
s[0] = FC_KENB_STAR;
// P0 = PCI (target physical cell id)
s[1] = (pci & 0x0000ff00) >> 8;
s[2] = (pci & 0x000000ff);
// L0 = length of PCI (i.e. 0x00 0x02)
s[3] = 0x00;
s[4] = 0x02;
// P1 = EARFCN-DL (target physical cell downlink frequency)
if (is_rel8_only) {
s[5] = (earfcn_dl & 0x0000ff00) >> 8;
s[6] = (earfcn_dl & 0x000000ff);
s[7] = 0x00;
s[8] = 0x02;
// kdf (kenb_32, 32, s, 9, kenb_star, 32);
data.len = 9;
if (alg == EIA0_ALG_ID) {
LOG_E(OSA, "Provided integrity algorithm is currently not supported = %u\n", alg);
} else if (alg == EIA1_128_ALG_ID) {
LOG_D(OSA, "EIA1 algorithm applied for integrity\n");
nas_stream_encrypt_eia1(stream_cipher, out);
} else if (alg == EIA2_128_ALG_ID) {
LOG_D(OSA, "EIA2 algorithm applied for integrity\n");
nas_stream_encrypt_eia2(stream_cipher, out);
} else {
s[5] = (earfcn_dl & 0x00ff0000) >> 16;
s[6] = (earfcn_dl & 0x0000ff00) >> 8;
s[7] = (earfcn_dl & 0x000000ff);
s[8] = 0x00;
s[9] = 0x03;
//kdf (kenb_32, 32, s, 10, kenb_star, 32);
data.len = 10;
LOG_E(OSA, "Provided integrity algorithm is currently not supported = %u\n", alg);
DevAssert(0 != 0 && "Unknown Algorithm type");
}
}
void stream_compute_encrypt(eea_alg_id_e alg, nas_stream_cipher_t const* stream_cipher, uint8_t* out)
{
if (alg == EEA0_ALG_ID) {
LOG_D(OSA, "EEA0 algorithm applied for encryption\n");
nas_stream_encrypt_eea0(stream_cipher, out);
} else if (alg == EEA1_128_ALG_ID) {
LOG_D(OSA, "EEA1 algorithm applied for encryption\n");
nas_stream_encrypt_eea1(stream_cipher, out);
} else if (alg == EEA2_128_ALG_ID) {
LOG_D(OSA, "EEA2 algorithm applied for encryption\n");
nas_stream_encrypt_eea2(stream_cipher, out);
} else {
LOG_E(OSA, "Provided encrypt algorithm is currently not supported = %u\n", alg);
DevAssert(0 != 0 && "Unknown Algorithm type");
}
kdf (kenb_32, data, 32, kenb_star);
// L1 length of EARFCN-DL (i.e. L1 = 0x00 0x02 if EARFCN-DL is between 0 and 65535, and L1 = 0x00 0x03 if EARFCN-DL is between 65536 and 262143)
// NOTE: The length of EARFCN-DL cannot be generally set to 3 bytes for backward compatibility reasons: A Rel-8
// entity (UE or eNB) would always assume an input parameter length of 2 bytes for the EARFCN-DL. This
// would lead to different derived keys if another entity assumed an input parameter length of 3 bytes for the
// EARFCN-DL.
return 0;
}
+25 -43
View File
@@ -22,47 +22,9 @@
#ifndef SECU_DEFS_H_
#define SECU_DEFS_H_
#include "security_types.h"
#include <stdbool.h>
#include <stdint.h>
#define EIA0_ALG_ID 0x00
#define EIA1_128_ALG_ID 0x01
#define EIA2_128_ALG_ID 0x02
#define EEA0_ALG_ID 0x00
#define EEA1_128_ALG_ID 0x01
#define EEA2_128_ALG_ID 0x02
#define SECU_DIRECTION_UPLINK 0
#define SECU_DIRECTION_DOWNLINK 1
int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB);
int derive_keNB_star(const uint8_t *kenb_32, const uint16_t pci, const uint32_t earfcn_dl,
const bool is_rel8_only, uint8_t * kenb_star);
int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
const uint8_t kasme[32], uint8_t *knas);
#define derive_key_nas_enc(aLGiD, kASME, kNAS) \
derive_key_nas(NAS_ENC_ALG, aLGiD, kASME, kNAS)
#define derive_key_nas_int(aLGiD, kASME, kNAS) \
derive_key_nas(NAS_INT_ALG, aLGiD, kASME, kNAS)
#define derive_key_rrc_enc(aLGiD, kASME, kNAS) \
derive_key_nas(RRC_ENC_ALG, aLGiD, kASME, kNAS)
#define derive_key_rrc_int(aLGiD, kASME, kNAS) \
derive_key_nas(RRC_INT_ALG, aLGiD, kASME, kNAS)
#define derive_key_up_enc(aLGiD, kASME, kNAS) \
derive_key_nas(UP_ENC_ALG, aLGiD, kASME, kNAS)
#define derive_key_up_int(aLGiD, kASME, kNAS) \
derive_key_nas(UP_INT_ALG, aLGiD, kASME, kNAS)
#define SECU_DIRECTION_UPLINK 0
#define SECU_DIRECTION_DOWNLINK 1
@@ -77,14 +39,34 @@ typedef struct {
uint32_t blength;
} nas_stream_cipher_t;
int nas_stream_encrypt_eea1(nas_stream_cipher_t *stream_cipher, uint8_t *out);
/*!
* @brief Encrypt/Decrypt a block of data based on the provided algorithm
* @param[in] algorithm Algorithm used to encrypt the data
* Possible values are:
* - EIA0_ALG_ID for NULL encryption
* - EIA1_128_ALG_ID for SNOW-3G encryption (not avalaible right now)
* - EIA2_128_ALG_ID for 128 bits AES LTE encryption
* @param[in] stream_cipher All parameters used to compute the encrypted block of data
* @param[out] out The encrypted block of data
*/
int nas_stream_encrypt_eia1(nas_stream_cipher_t *stream_cipher, uint8_t out[4]);
typedef enum {
EIA0_ALG_ID = 0x00,
EIA1_128_ALG_ID = 0x01,
EIA2_128_ALG_ID = 0x02,
END_EIA0_ALG_ID,
} eia_alg_id_e;
int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t *out);
void stream_compute_integrity(eia_alg_id_e alg, nas_stream_cipher_t const *stream_cipher, uint8_t out[4]);
int nas_stream_encrypt_eia2(nas_stream_cipher_t *stream_cipher, uint8_t out[4]);
typedef enum {
EEA0_ALG_ID = 0x00,
EEA1_128_ALG_ID = 0x01,
EEA2_128_ALG_ID = 0x02,
#undef SECU_DEBUG
END_EEA_ALG_ID
} eea_alg_id_e;
void stream_compute_encrypt(eea_alg_id_e alg, nas_stream_cipher_t const *stream_cipher, uint8_t *out);
#endif /* SECU_DEFS_H_ */
+1 -2
View File
@@ -52,8 +52,7 @@ void eea1_encrypt(uint8_t direction, uint32_t count,
nas_cipher->blength = length;
nas_cipher->message = message;
if (nas_stream_encrypt_eea1(nas_cipher, result) != 0)
fail("Fail: nas_stream_encrypt_eea1\n");
stream_compute_encrypt(EEA1_128_ALG_ID, nas_cipher, result);
if (compare_buffer(result, byte_length, expected, byte_length) != 0) {
fail("Fail: eea1_encrypt\n");
+1 -3
View File
@@ -25,7 +25,6 @@
#include <unistd.h>
#include "test_util.h"
#include "secu_defs.h"
static
@@ -52,8 +51,7 @@ void eea2_encrypt(uint8_t direction, uint32_t count,
nas_cipher->blength = length;
nas_cipher->message = message;
if (nas_stream_encrypt_eea2(nas_cipher, result) != 0)
fail("Fail: nas_stream_encrypt_eea2\n");
nas_stream_encrypt_eea2(nas_cipher, result);
if (compare_buffer(result, byte_length, expected, byte_length) != 0) {
fail("Fail: eea2_encrypt\n");