Remove nettle library from OAI, support OpenSSL 3.0 and 1.1

Add byte_array_t structure under common/
This commit is contained in:
mir
2023-02-10 16:49:54 +01:00
committed by Robert Schmidt
parent 0afa3f3193
commit 986a1a80ff
58 changed files with 1500 additions and 936 deletions
+88
View File
@@ -0,0 +1,88 @@
/*
* 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_OAI_H
#define AES_128_OAI_H
#include <endian.h>
#include <stdint.h>
#include <stdlib.h>
// see 33.401 B.2.3 for the input to 128-EIA2
// (which is identical to 128-NIA2, see 33.501 D.3.1.3)
typedef struct {
uint32_t count;
uint8_t padding: 2;
uint8_t direction: 1;
uint8_t bearer: 5;
uint8_t pad_8;
uint16_t pad_16;
uint64_t pad_64;
} data_iv16_t;
typedef struct{
union{
data_iv16_t d;
uint8_t iv[16];
};
} iv16_t;
typedef struct {
uint32_t count;
uint8_t padding: 2;
uint8_t direction: 1;
uint8_t bearer: 5;
uint8_t pad_8;
uint16_t pad_16;
} data_iv8_t;
typedef struct{
union{
data_iv8_t d;
uint8_t iv[8];
};
} iv8_t;
typedef enum{
AES_INITIALIZATION_VECTOR_8,
AES_INITIALIZATION_VECTOR_16,
AES_INITIALIZATION_VECTOR_END,
} iv_e;
#if __BYTE_ORDER == __BIG_ENDIAN
static_assert(0 != 0, "The struct iv_t needs little endianness");
#endif
// static_assert((16 == sizeof(iv_t)) , "Initialization Vector needs to have an AES_BLOCK_SIZE" );
typedef struct {
uint8_t key[16];
iv_e type;
union{
iv8_t iv8;
iv16_t iv16;
};
} aes_128_t;
#endif
+254
View File
@@ -0,0 +1,254 @@
/*
* 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 <assert.h>
#include <stdlib.h>
#include <string.h>
#include "aes_128_cbc_cmac.h"
#include "common/utils/assertions.h"
#include <openssl/cmac.h>
#if OPENSSL_VERSION_MAJOR >= 3
// code for version 3.0 or greater
#include <openssl/core_names.h>
static
const char *propq = NULL;
void aes_128_cbc_cmac(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out])
{
OSSL_LIB_CTX* library_context = OSSL_LIB_CTX_new();
DevAssert(library_context != NULL);
/* Fetch the CMAC implementation */
EVP_MAC* mac = EVP_MAC_fetch(library_context, "CMAC", propq);
DevAssert(mac != NULL);
/* Create a context for the CMAC operation */
EVP_MAC_CTX* mctx = EVP_MAC_CTX_new(mac);
DevAssert(mctx != NULL);
// The underlying cipher to be used
char cipher_name[] = "aes128";
OSSL_PARAM params[2] = {0};
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, cipher_name,
sizeof(cipher_name));
params[1] = OSSL_PARAM_construct_end();
/* Initialise the CMAC operation */
int rc = EVP_MAC_init(mctx, k_iv->key, sizeof(k_iv->key), params);
DevAssert(rc != 0);
size_t sz_iv = 0;
uint8_t* iv = NULL;
if(k_iv->type == AES_INITIALIZATION_VECTOR_8){
sz_iv = 8;
iv = (uint8_t*)k_iv->iv8.iv;
} else if(k_iv->type == AES_INITIALIZATION_VECTOR_16) {
sz_iv = 16;
iv = (uint8_t*)k_iv->iv16.iv;
} else {
DevAssert(0!=0 && "Unknwon Initialization vector");
}
/* Make one or more calls to process the data to be authenticated */
rc = EVP_MAC_update(mctx, iv, sz_iv);
DevAssert(rc != 0);
/* Make one or more calls to process the data to be authenticated */
rc = EVP_MAC_update(mctx, msg.buf, msg.len);
DevAssert(rc != 0);
/* Make a call to the final with a NULL buffer to get the length of the MAC */
size_t out_len = 0;
rc = EVP_MAC_final(mctx, out, &out_len, len_out);
DevAssert(rc != 0);
EVP_MAC_CTX_free(mctx);
EVP_MAC_free(mac);
OSSL_LIB_CTX_free(library_context);
}
cbc_cmac_ctx_t init_aes_128_cbc_cmac(uint8_t key[16])
{
DevAssert(key != NULL);
OSSL_LIB_CTX* library_context = OSSL_LIB_CTX_new();
DevAssert(library_context != NULL);
/* Fetch the CMAC implementation */
EVP_MAC* mac = EVP_MAC_fetch(library_context, "CMAC", propq);
DevAssert(mac != NULL);
cbc_cmac_ctx_t ctx = {.lib_ctx = library_context, .mac = mac };
assert(16 == sizeof(ctx.key));
memcpy(ctx.key, key, 16);
return ctx;
}
void cipher_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx, const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out])
{
DevAssert(ctx != NULL);
DevAssert(k_iv != NULL);
/* Create a context for the CMAC operation */
EVP_MAC_CTX* mctx = EVP_MAC_CTX_new(ctx->mac);
DevAssert(mctx != NULL);
// The underlying cipher to be used
char cipher_name[] = "aes128";
OSSL_PARAM params[2] = {0};
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER, cipher_name,
sizeof(cipher_name));
params[1] = OSSL_PARAM_construct_end();
/* Initialise the CMAC operation */
int rc = EVP_MAC_init(mctx, k_iv->key, sizeof(k_iv->key), params);
DevAssert(rc != 0);
size_t sz_iv = 0;
uint8_t* iv = NULL;
if(k_iv->type == AES_INITIALIZATION_VECTOR_8){
sz_iv = 8;
iv = (uint8_t*)k_iv->iv8.iv;
} else if(k_iv->type == AES_INITIALIZATION_VECTOR_16) {
sz_iv = 16;
iv = (uint8_t*)k_iv->iv16.iv;
} else {
DevAssert(0!=0 && "Unknwon Initialization vector");
}
/* Make one or more calls to process the data to be authenticated */
rc = EVP_MAC_update(mctx, iv, sz_iv);
DevAssert(rc != 0);
/* Make one or more calls to process the data to be authenticated */
rc = EVP_MAC_update(mctx, msg.buf, msg.len);
DevAssert(rc != 0);
/* Make a call to the final with a NULL buffer to get the length of the MAC */
size_t out_len = 0;
rc = EVP_MAC_final(mctx, out, &out_len, len_out);
DevAssert(rc != 0);
EVP_MAC_CTX_free(mctx);
}
void free_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx)
{
DevAssert(ctx != NULL);
EVP_MAC_free(ctx->mac);
OSSL_LIB_CTX_free(ctx->lib_ctx);
}
#else
// code for 1.1.x or lower
void aes_128_cbc_cmac(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out])
{
DevAssert(k_iv != NULL);
CMAC_CTX *ctx = CMAC_CTX_new();
DevAssert(ctx != NULL);
CMAC_Init(ctx, k_iv->key, sizeof(k_iv->key), EVP_aes_128_cbc(), NULL);
size_t sz_iv = 0;
uint8_t* iv = NULL;
if(k_iv->type == AES_INITIALIZATION_VECTOR_8){
sz_iv = 8;
iv = (uint8_t*)k_iv->iv8.iv;
} else if(k_iv->type == AES_INITIALIZATION_VECTOR_16) {
sz_iv = 16;
iv = (uint8_t*)k_iv->iv16.iv;
} else {
DevAssert(0!=0 && "Unknwon Initialization vector");
}
CMAC_Update(ctx, iv, sz_iv);
CMAC_Update(ctx, msg.buf, msg.len);
size_t len_res = 0;
CMAC_Final(ctx, out, &len_res);
DevAssert(len_res <= len_out);
CMAC_CTX_free(ctx);
}
cbc_cmac_ctx_t init_aes_128_cbc_cmac(uint8_t key[16])
{
DevAssert(key != NULL);
cbc_cmac_ctx_t ctx = {.lib_ctx = NULL, .mac = NULL };
ctx.mac = CMAC_CTX_new();
DevAssert(ctx.mac != NULL);
//assert(16 == sizeof(ctx.key));
memcpy(ctx.key, key, 16); //sizeof(ctx.key));
CMAC_Init(ctx.mac, ctx.key, 16, EVP_aes_128_cbc(), NULL);
return ctx;
}
void cipher_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx, const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out])
{
DevAssert(ctx != NULL);
DevAssert(k_iv != NULL);
//From https://man.openbsd.org/CMAC_Init.3
//If ctx is already initialized, CMAC_Init() can be called again with key,
//cipher, and impl all set to NULL and key_len set to 0. In that case, any
//data already processed is discarded and ctx is re-initialized to start
//reading data anew.
CMAC_Init(ctx->mac, NULL, 0, NULL, NULL);
size_t sz_iv = 0;
uint8_t* iv = NULL;
if(k_iv->type == AES_INITIALIZATION_VECTOR_8){
sz_iv = 8;
iv = (uint8_t*)k_iv->iv8.iv;
} else if(k_iv->type == AES_INITIALIZATION_VECTOR_16) {
sz_iv = 16;
iv = (uint8_t*)k_iv->iv16.iv;
} else {
DevAssert(0!=0 && "Unknwon Initialization vector");
}
CMAC_Update(ctx->mac, iv, sz_iv);
CMAC_Update(ctx->mac, msg.buf, msg.len);
size_t len_res = 0;
CMAC_Final(ctx->mac, out, &len_res);
DevAssert(len_res <= len_out);
}
void free_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx)
{
DevAssert(ctx != NULL);
CMAC_CTX_free(ctx->mac);
}
#endif
+48
View File
@@ -0,0 +1,48 @@
/*
* 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_CBC_CMAC_H
#define AES_128_CBC_CMAC_H
#include "aes_128.h"
#include "common/utils/ds/byte_array.h"
#include <stdint.h>
#include <stdlib.h>
typedef struct {
void* lib_ctx;
void* mac;
uint8_t key[16];
} cbc_cmac_ctx_t ;
void aes_128_cbc_cmac(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out]);
cbc_cmac_ctx_t init_aes_128_cbc_cmac(uint8_t key[16]);
void cipher_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx, const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out]);
void free_aes_128_cbc_cmac(cbc_cmac_ctx_t const* ctx);
#endif
+62
View File
@@ -0,0 +1,62 @@
/*
* 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
*/
// TS 133 401 pag. 88
#include "aes_128_ctr.h"
#include "common/utils/assertions.h"
#include <openssl/aes.h>
#include <openssl/err.h>
#include <openssl/evp.h>
void aes_128_ctr(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out])
{
DevAssert(k_iv != NULL);
DevAssert(sizeof(iv16_t) == AES_BLOCK_SIZE);
DevAssert(k_iv->type == AES_INITIALIZATION_VECTOR_16);
// Create and initialise the context
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
DevAssert(ctx != NULL);
// Set IV length if default 12 bytes (96 bits) is not appropriate
// int rc = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CTR_SET_IVLEN, 16, NULL))
// Initialise the encryption operation.
int rc = EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, k_iv->key, k_iv->iv16.iv);
DevAssert(rc == 1);
OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == AES_BLOCK_SIZE);
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);
}
+33
View File
@@ -0,0 +1,33 @@
/*
* 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_CTR_OAI_H
#define AES_128_CTR_OAI_H
#include "aes_128.h"
#include "common/utils/ds/byte_array.h"
#include <endian.h>
#include <stdint.h>
#include <stdlib.h>
void aes_128_ctr(const aes_128_t* k_iv, byte_array_t msg, size_t len_out, uint8_t out[len_out]);
#endif
+6 -75
View File
@@ -19,87 +19,18 @@
* contact@openairinterface.org
*/
#include "common/utils/assertions.h"
#include "openair3/SECU/sha_256_hmac.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <nettle/hmac.h>
#include "security_types.h"
#include "secu_defs.h"
#include "kdf.h"
void kdf(const uint8_t *key, uint16_t key_len, uint8_t *s, uint16_t s_len, uint8_t *out,
uint16_t out_len)
void kdf(const uint8_t key[32], byte_array_t data, size_t len, uint8_t out[len])
{
struct hmac_sha256_ctx ctx;
memset(&ctx, 0, sizeof(ctx));
hmac_sha256_set_key(&ctx, key_len, key);
hmac_sha256_update(&ctx, s_len, s);
hmac_sha256_digest(&ctx, out_len, out);
// Do we still need kdf function?
sha_256_hmac(key, data, len, out);
}
#ifndef NAS_UE
int derive_keNB(const uint8_t kasme[32], const uint32_t nas_count, uint8_t *keNB)
{
uint8_t s[7];
// 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);
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};
// 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);
} 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);
}
// 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;
}
+34
View File
@@ -0,0 +1,34 @@
/*
* 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 KEY_DERIVATION_FUNCTION_OSA_H
#define KEY_DERIVATION_FUNCTION_OSA_H
#include <stdint.h>
#include <stdlib.h>
#include "byte_array.h"
void kdf(const uint8_t key[32], byte_array_t data, size_t len, uint8_t out[len]);
#endif
+4 -1
View File
@@ -26,6 +26,7 @@
#include "security_types.h"
#include "secu_defs.h"
#include "kdf.h"
#define SECU_DEBUG 1
/*!
@@ -79,7 +80,9 @@ int derive_key_nas(algorithm_type_dist_t nas_alg_type, uint8_t nas_enc_alg_id,
printf("\n");
#endif
kdf(kasme, 32, s, 7, out, 32);
//kdf(kasme, 32, s, 7, out, 32);
byte_array_t data = {.len = 7, .buf = s};
kdf(kasme, data, 32, out);
memcpy(knas, &out[31-16+1], 16);
-4
View File
@@ -24,10 +24,6 @@
#include <stdint.h>
#include <string.h>
#include <nettle/nettle-meta.h>
#include <nettle/aes.h>
#include <nettle/ctr.h>
#include "assertions.h"
#include "conversions.h"
#include "secu_defs.h"
+20 -64
View File
@@ -19,84 +19,40 @@
* contact@openairinterface.org
*/
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <nettle/nettle-meta.h>
#include <nettle/aes.h>
#include <nettle/ctr.h>
#include "aes_128_ctr.h"
#include "assertions.h"
#include "conversions.h"
#include "secu_defs.h"
// #define SECU_DEBUG
int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t *out)
{
uint8_t m[16];
uint32_t local_count;
void *ctx;
uint8_t *data;
uint32_t zero_bit = 0;
uint32_t byte_length;
DevAssert(stream_cipher != NULL);
DevAssert(out != 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);
zero_bit = stream_cipher->blength & 0x7;
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;
byte_length = stream_cipher->blength >> 3;
if (zero_bit > 0)
byte_length += 1;
ctx = malloc(nettle_aes128.context_size);
data = malloc(byte_length);
local_count = hton_int32(stream_cipher->count);
memset(m, 0, sizeof(m));
memcpy(&m[0], &local_count, 4);
m[4] = ((stream_cipher->bearer & 0x1F) << 3) |
((stream_cipher->direction & 0x01) << 2);
/* Other bits are 0 */
#if defined(SECU_DEBUG)
{
int i;
printf("Blength: %u, Zero bits: %u\n", stream_cipher->blength, zero_bit);
for (i = 0; i < sizeof(m); i++)
printf("0x%02x ", m[i]);
printf("\n");
}
#endif
#if NETTLE_VERSION_MAJOR < 3
nettle_aes128.set_encrypt_key(ctx, stream_cipher->key_length,
stream_cipher->key);
#else
nettle_aes128.set_encrypt_key(ctx,
stream_cipher->key);
#endif
nettle_ctr_crypt(ctx, nettle_aes128.encrypt,
nettle_aes128.block_size, m,
byte_length, data, stream_cipher->message);
if (zero_bit > 0)
data[byte_length - 1] = data[byte_length - 1] & (uint8_t)(0xFF << (8 - zero_bit));
memcpy(out, data, byte_length);
free(data);
free(ctx);
DevAssert((stream_cipher->blength & 0x07) == 0);
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;
}
+21 -83
View File
@@ -19,6 +19,7 @@
* contact@openairinterface.org
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
@@ -26,15 +27,8 @@
#include "secu_defs.h"
#include <openssl/aes.h>
#include <openssl/cmac.h>
#include <openssl/evp.h>
// test
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include <arpa/inet.h>
#include "aes_128_cbc_cmac.h"
#include "assertions.h"
#include "conversions.h"
@@ -45,84 +39,28 @@
* @param[in] stream_cipher Structure containing various variables to setup encoding
* @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])
{
uint8_t *m = NULL;
uint32_t local_count;
size_t size = 4;
uint8_t data[16];
CMAC_CTX *cmac_ctx = NULL;
const EVP_CIPHER *cipher = EVP_aes_128_cbc();
uint32_t zero_bit = 0;
uint32_t m_length;
int ret;
DevAssert(stream_cipher != NULL);
DevAssert(stream_cipher->key != NULL);
DevAssert(stream_cipher->key_length > 0);
DevAssert(out != NULL);
DevAssert(stream_cipher->message != NULL);
DevAssert(stream_cipher->bearer < 32);
DevAssert(stream_cipher->key_length == 16);
DevAssert((stream_cipher->blength & 0x7) == 0);
memset(data, 0, 16);
zero_bit = stream_cipher->blength & 0x7;
m_length = stream_cipher->blength >> 3;
if (zero_bit > 0)
m_length += 1;
local_count = hton_int32(stream_cipher->count);
m = calloc(m_length + 8, sizeof(uint8_t));
memcpy(&m[0], &local_count, 4);
m[4] = ((stream_cipher->bearer & 0x1F) << 3) | ((stream_cipher->direction & 0x01) << 2);
memcpy(&m[8], stream_cipher->message, m_length);
#if defined(SECU_DEBUG)
{
int i;
printf("Byte length: %u, Zero bits: %u\nm: ", m_length + 8, zero_bit);
for (i = 0; i < m_length + 8; i++)
printf("%02x", m[i]);
printf("\nKey:");
for (i = 0; i < stream_cipher->key_length; i++)
printf("%02x", stream_cipher->key[i]);
printf("\nMessage:");
for (i = 0; i < m_length; i++)
printf("%02x", stream_cipher->message[i]);
printf("\n");
}
#endif
cmac_ctx = CMAC_CTX_new();
ret = CMAC_Init(cmac_ctx, stream_cipher->key, stream_cipher->key_length, cipher, NULL);
ret = CMAC_Update(cmac_ctx, m, m_length + 8);
(void)ret; /* avoid gcc warning "set but not used" */
CMAC_Final(cmac_ctx, data, &size);
CMAC_CTX_free(cmac_ctx);
#if defined(SECU_DEBUG)
{
int i;
printf("out: ");
for (i = 0; i < size; i++)
printf("%02x", data[i]);
printf("\n");
}
#endif
memcpy(out, data, 4);
free(m);
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);
size_t const m_length = stream_cipher->blength >> 3;
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;
}
+96
View File
@@ -0,0 +1,96 @@
/*
* 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 "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)
{
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;
} 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;
}
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;
}
+1 -7
View File
@@ -24,6 +24,7 @@
#include "security_types.h"
#include <stdbool.h>
#include <stdint.h>
#define EIA0_ALG_ID 0x00
#define EIA1_128_ALG_ID 0x01
@@ -36,13 +37,6 @@
#define SECU_DIRECTION_UPLINK 0
#define SECU_DIRECTION_DOWNLINK 1
void kdf(const uint8_t *key,
uint16_t key_len,
uint8_t *s,
uint16_t s_len,
uint8_t *out,
uint16_t out_len);
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,
+95
View File
@@ -0,0 +1,95 @@
/*
* 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 "common/utils/assertions.h"
#include "sha_256_hmac.h"
#include <openssl/hmac.h>
#if OPENSSL_VERSION_MAJOR >= 3
// code for version 3.0 or greater
#include <openssl/core_names.h>
void sha_256_hmac(const uint8_t key[32], byte_array_t data, size_t len, uint8_t out[len])
{
DevAssert(key != NULL);
DevAssert(data.buf != NULL);
DevAssert(data.len != 0);
DevAssert(len != 0);
OSSL_LIB_CTX* library_context = OSSL_LIB_CTX_new();
DevAssert(library_context != NULL);
// A property query used for selecting the MAC implementation.
const char* propq = NULL;
// Fetch the HMAC implementation
EVP_MAC* mac = EVP_MAC_fetch(library_context, "HMAC", propq);
DevAssert(mac != NULL);
// Create a context for the HMAC operation
EVP_MAC_CTX* mctx = EVP_MAC_CTX_new(mac);
DevAssert(mctx != NULL);
// The underlying digest to be used
OSSL_PARAM params[2] = {0};
char digest_name[] = "SHA2-256";
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, digest_name, sizeof(digest_name));
params[1] = OSSL_PARAM_construct_end();
// Initialise the HMAC operation
int rc = EVP_MAC_init(mctx, key, 32, params);
DevAssert(rc == 1);
// Make one or more calls to process the data to be authenticated
rc = EVP_MAC_update(mctx, data.buf, data.len);
DevAssert(rc == 1);
// Make one call to the final to get the MAC
rc = EVP_MAC_final(mctx, out, &len, len);
DevAssert(rc == 1);
// OpenSSL free functions will ignore NULL arguments
EVP_MAC_CTX_free(mctx);
EVP_MAC_free(mac);
OSSL_LIB_CTX_free(library_context);
}
#else
// code for 1.1.x or lower
void sha_256_hmac(const uint8_t key[32], byte_array_t data, size_t len, uint8_t out[len])
{
DevAssert(key != NULL);
DevAssert(data.buf != NULL);
DevAssert(data.len != 0);
DevAssert(len != 0);
HMAC_CTX* ctx = HMAC_CTX_new();
HMAC_Init_ex(ctx, key, 32, EVP_sha256(), NULL);
HMAC_Update(ctx, data.buf, data.len);
HMAC_Final(ctx, out, (uint32_t*)&len);
HMAC_CTX_free(ctx);
}
#endif
+33
View File
@@ -0,0 +1,33 @@
/*
* 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 SHA_256_HMAC_OAI_H
#define SHA_256_HMAC_OAI_H
#include <stdint.h>
#include <stdlib.h>
#include "byte_array.h"
void sha_256_hmac(const uint8_t key[32], byte_array_t data, size_t len, uint8_t out[len]);
#endif