srsLTE/lib/src/common/liblte_security.cc

1358 lines
42 KiB
C++

/**
*
* \section COPYRIGHT
*
* Copyright 2014 Ben Wojtowicz
* 2016-2020 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
/*******************************************************************************
INCLUDES
*******************************************************************************/
#include "srsran/common/liblte_security.h"
#include "math.h"
#include "srsran/common/s3g.h"
#include "srsran/common/ssl.h"
#include "srsran/common/zuc.h"
#include <arpa/inet.h>
/*******************************************************************************
LOCAL FUNCTION PROTOTYPES
*******************************************************************************/
/*********************************************************************
Name: zero_tailing_bits
Description: Fill tailing bits with zeros.
Document Reference: -
*********************************************************************/
void zero_tailing_bits(uint8* data, uint32 length_bits);
/*******************************************************************************
FUNCTIONS
*******************************************************************************/
/*********************************************************************
Name: liblte_security_generate_k_asme
Description: Generate the security key Kasme.
Document Reference: 33.401 v10.0.0 Annex A.2
*********************************************************************/
LIBLTE_ERROR_ENUM
liblte_security_generate_k_asme(uint8* ck, uint8* ik, uint8* ak, uint8* sqn, uint16 mcc, uint16 mnc, uint8* k_asme)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint32 i;
uint8 s[14];
uint8 key[32];
if (ck != NULL && ik != NULL && ak != NULL && sqn != NULL && k_asme != NULL) {
// Construct S
s[0] = 0x10; // FC
s[1] = (mcc & 0x00F0) | ((mcc & 0x0F00) >> 8); // First byte of P0
if ((mnc & 0xFF00) == 0xFF00) {
// 2-digit MNC
s[2] = 0xF0 | (mcc & 0x000F); // Second byte of P0
s[3] = ((mnc & 0x000F) << 4) | ((mnc & 0x00F0) >> 4); // Third byte of P0
} else {
// 3-digit MNC
s[2] = ((mnc & 0x000F) << 4) | (mcc & 0x000F); // Second byte of P0
s[3] = ((mnc & 0x00F0)) | ((mnc & 0x0F00) >> 8); // Third byte of P0
}
s[4] = 0x00; // First byte of L0
s[5] = 0x03; // Second byte of L0
for (i = 0; i < 6; i++) {
s[6 + i] = sqn[i] ^ ak[i]; // P1
}
s[12] = 0x00; // First byte of L1
s[13] = 0x06; // Second byte of L1
// Construct Key
for (i = 0; i < 16; i++) {
key[i] = ck[i];
key[16 + i] = ik[i];
}
// Derive Kasme
sha256(key, 32, s, 14, k_asme, 0);
err = LIBLTE_SUCCESS;
}
return (err);
}
/*********************************************************************
Name: liblte_security_generate_k_enb
Description: Generate the security key Kenb.
Document Reference: 33.401 v10.0.0 Annex A.2
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_generate_k_enb(uint8* k_asme, uint32 nas_count, uint8* k_enb)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 s[7];
if (k_asme != NULL && k_enb != NULL) {
// Construct S
s[0] = 0x11; // FC
s[1] = (nas_count >> 24) & 0xFF; // First byte of P0
s[2] = (nas_count >> 16) & 0xFF; // Second byte of P0
s[3] = (nas_count >> 8) & 0xFF; // Third byte of P0
s[4] = nas_count & 0xFF; // Fourth byte of P0
s[5] = 0x00; // First byte of L0
s[6] = 0x04; // Second byte of L0
// Derive Kenb
sha256(k_asme, 32, s, 7, k_enb, 0);
err = LIBLTE_SUCCESS;
}
return (err);
}
LIBLTE_ERROR_ENUM liblte_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)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8_t key[32];
uint8_t* s;
if (ck != NULL && ik != NULL && serving_network_name != NULL && rand != NULL && res != NULL && res_star != NULL) {
// Construct S
uint16_t ssn_length = strlen(serving_network_name);
uint16_t rand_length = 16;
uint32_t s_len = 1 + ssn_length + 2 + rand_length + 2 + res_len + 2;
uint8_t output[32] = {};
s = (uint8_t*)calloc(s_len, sizeof(uint8_t));
if (s == nullptr) {
return err;
}
uint32_t i = 0;
s[i] = 0x6B; // FC
i++;
// SSN
memcpy(&s[i], serving_network_name, strlen(serving_network_name));
i += ssn_length;
uint16_t ssn_length_value = htons(ssn_length);
memcpy(&s[i], &ssn_length_value, sizeof(ssn_length));
i += sizeof(ssn_length_value);
// RAND
memcpy(&s[i], rand, rand_length);
i += rand_length;
uint16_t rand_length_value = htons(rand_length);
memcpy(&s[i], &rand_length_value, sizeof(rand_length));
i += sizeof(rand_length_value);
// RES
memcpy(&s[i], res, res_len);
i += res_len;
uint16_t res_length_value = htons(res_len);
memcpy(&s[i], &res_length_value, sizeof(res_length_value));
i += sizeof(res_length_value);
// The input key Key shall be equal to the concatenation CK || IK of CK and IK.
memcpy(key, ck, 16);
memcpy(key + 16, ik, 16);
// Derive output
sha256(key, 32, s, s_len, output, 0);
memcpy(res_star, output + 16, 16);
free(s);
err = LIBLTE_SUCCESS;
}
return (err);
}
/*********************************************************************
Name: liblte_security_generate_k_enb_star
Description: Generate the security key Kenb*.
Document Reference: 33.401 v10.0.0 Annex A.5
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_generate_k_enb_star(uint8* k_enb, uint32 pci, uint32_t earfcn, uint8* k_enb_star)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 s[9];
if (k_enb_star != NULL && k_enb != NULL) {
// Construct S
s[0] = 0x13; // FC
s[1] = (pci >> 8) & 0xFF; // First byte of P0
s[2] = pci & 0xFF; // Second byte of P0
s[3] = 0x00; // First byte of L0
s[4] = 0x02; // Second byte of L0
s[5] = (earfcn >> 8) & 0xFF; // First byte of P0
s[6] = earfcn & 0xFF; // Second byte of P0
s[7] = 0x00; // First byte of L0
s[8] = 0x02; // Second byte of L0
// Derive Kenb
sha256(k_enb, 32, s, 9, k_enb_star, 0);
err = LIBLTE_SUCCESS;
}
return (err);
}
LIBLTE_ERROR_ENUM liblte_security_generate_nh(uint8_t* k_asme, uint8_t* sync, uint8_t* nh)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 s[35];
if (k_asme != NULL && sync != NULL && nh != NULL) {
// Construct S
s[0] = 0x12; // FC
for (int i = 0; i < 32; i++) {
s[1 + i] = sync[i];
}
s[33] = 0x00; // First byte of L0
s[34] = 0x20, // Second byte of L0
// Derive NH
sha256(k_asme, 32, s, 35, nh, 0);
err = LIBLTE_SUCCESS;
}
return (err);
}
/*********************************************************************
Name: liblte_security_generate_k_nas
Description: Generate the NAS security keys KNASenc and KNASint.
Document Reference: 33.401 v10.0.0 Annex A.2
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_generate_k_nas(uint8* k_asme,
LIBLTE_SECURITY_CIPHERING_ALGORITHM_ID_ENUM enc_alg_id,
LIBLTE_SECURITY_INTEGRITY_ALGORITHM_ID_ENUM int_alg_id,
uint8* k_nas_enc,
uint8* k_nas_int)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 s[7];
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);
}
if (k_asme != NULL && k_nas_int != NULL) {
// Construct S for KNASint
s[0] = 0x15; // FC
s[1] = 0x02; // 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 KNASint
sha256(k_asme, 32, s, 7, k_nas_int, 0);
err = LIBLTE_SUCCESS;
}
return (err);
}
/*********************************************************************
Name: liblte_security_generate_k_rrc
Description: Generate the RRC security keys KRRCenc and KRRCint.
Document Reference: 33.401 v10.0.0 Annex A.2
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_generate_k_rrc(uint8* k_enb,
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_enb != NULL && k_rrc_enc != NULL && k_rrc_int != NULL) {
// Construct S for KRRCenc
s[0] = 0x15; // 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_enb, 32, s, 7, k_rrc_enc, 0);
// Construct S for KRRCint
s[0] = 0x15; // 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_enb, 32, s, 7, k_rrc_int, 0);
err = LIBLTE_SUCCESS;
}
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
Description: Generate the user plane security keys KUPenc and
KUPint.
Document Reference: 33.401 v10.0.0 Annex A.2
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_generate_k_up(uint8* k_enb,
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_enb != NULL && k_up_enc != NULL && k_up_int != NULL) {
// Construct S for KUPenc
s[0] = 0x15; // 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_enb, 32, s, 7, k_up_enc, 0);
// Construct S for KUPint
s[0] = 0x15; // 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_enb, 32, s, 7, k_up_int, 0);
err = LIBLTE_SUCCESS;
}
return (err);
}
LIBLTE_ERROR_ENUM liblte_security_128_eia1(const uint8* key,
uint32 count,
uint8 bearer,
uint8 direction,
uint8* msg,
uint32 msg_len,
uint8* mac)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if (key != NULL && msg != NULL && mac != NULL) {
uint32_t msg_len_bits = 0;
uint32_t i = 0;
uint8_t* m_ptr;
msg_len_bits = msg_len * 8;
m_ptr = s3g_f9(key, count, bearer << 27, direction, msg, msg_len_bits);
for (i = 0; i < 4; i++) {
mac[i] = m_ptr[i];
}
err = LIBLTE_SUCCESS;
}
return (err);
}
/*********************************************************************
Name: liblte_security_128_eia2
Description: 128-bit integrity algorithm EIA2.
Document Reference: 33.401 v10.0.0 Annex B.2.3
33.102 v10.0.0 Section 6.5.4
RFC4493
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_128_eia2(const uint8* key,
uint32 count,
uint8 bearer,
uint8 direction,
uint8* msg,
uint32 msg_len,
uint8* mac)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8 M[msg_len + 8 + 16];
aes_context ctx;
uint32 i;
uint32 j;
uint32 n;
uint32 pad_bits;
uint8 const_zero[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8 L[16];
uint8 K1[16];
uint8 K2[16];
uint8 T[16];
uint8 tmp[16];
if (key != NULL && msg != NULL && mac != NULL) {
// Subkey L generation
aes_setkey_enc(&ctx, key, 128);
aes_crypt_ecb(&ctx, AES_ENCRYPT, const_zero, L);
// Subkey K1 generation
for (i = 0; i < 15; i++) {
K1[i] = (L[i] << 1) | ((L[i + 1] >> 7) & 0x01);
}
K1[15] = L[15] << 1;
if (L[0] & 0x80) {
K1[15] ^= 0x87;
}
// Subkey K2 generation
for (i = 0; i < 15; i++) {
K2[i] = (K1[i] << 1) | ((K1[i + 1] >> 7) & 0x01);
}
K2[15] = K1[15] << 1;
if (K1[0] & 0x80) {
K2[15] ^= 0x87;
}
// Construct M
memset(M, 0, msg_len + 8 + 16);
M[0] = (count >> 24) & 0xFF;
M[1] = (count >> 16) & 0xFF;
M[2] = (count >> 8) & 0xFF;
M[3] = count & 0xFF;
M[4] = (bearer << 3) | (direction << 2);
for (i = 0; i < msg_len; i++) {
M[8 + i] = msg[i];
}
// MAC generation
n = (uint32)(ceilf((float)(msg_len + 8) / (float)(16)));
for (i = 0; i < 16; i++) {
T[i] = 0;
}
for (i = 0; i < n - 1; i++) {
for (j = 0; j < 16; j++) {
tmp[j] = T[j] ^ M[i * 16 + j];
}
aes_crypt_ecb(&ctx, AES_ENCRYPT, tmp, T);
}
pad_bits = ((msg_len * 8) + 64) % 128;
if (pad_bits == 0) {
for (j = 0; j < 16; j++) {
tmp[j] = T[j] ^ K1[j] ^ M[i * 16 + j];
}
aes_crypt_ecb(&ctx, AES_ENCRYPT, tmp, T);
} else {
pad_bits = (128 - pad_bits) - 1;
M[i * 16 + (15 - (pad_bits / 8))] |= 0x1 << (pad_bits % 8);
for (j = 0; j < 16; j++) {
tmp[j] = T[j] ^ K2[j] ^ M[i * 16 + j];
}
aes_crypt_ecb(&ctx, AES_ENCRYPT, tmp, T);
}
for (i = 0; i < 4; i++) {
mac[i] = T[i];
}
err = LIBLTE_SUCCESS;
}
return (err);
}
LIBLTE_ERROR_ENUM liblte_security_128_eia2(const uint8* key,
uint32 count,
uint8 bearer,
uint8 direction,
LIBLTE_BIT_MSG_STRUCT* msg,
uint8* mac)
{
if (!key || !msg || !mac) {
return LIBLTE_ERROR_INVALID_INPUTS;
}
uint8 M[msg->N_bits * 8 + 8 + 16];
aes_context ctx;
uint32 i;
uint32 j;
uint32 n;
uint32 pad_bits;
uint8 const_zero[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8 L[16];
uint8 K1[16];
uint8 K2[16];
uint8 T[16];
uint8 tmp[16];
// Subkey L generation
aes_setkey_enc(&ctx, key, 128);
aes_crypt_ecb(&ctx, AES_ENCRYPT, const_zero, L);
// Subkey K1 generation
for (i = 0; i < 15; i++) {
K1[i] = (L[i] << 1) | ((L[i + 1] >> 7) & 0x01);
}
K1[15] = L[15] << 1;
if (L[0] & 0x80) {
K1[15] ^= 0x87;
}
// Subkey K2 generation
for (i = 0; i < 15; i++) {
K2[i] = (K1[i] << 1) | ((K1[i + 1] >> 7) & 0x01);
}
K2[15] = K1[15] << 1;
if (K1[0] & 0x80) {
K2[15] ^= 0x87;
}
// Construct M
memset(M, 0, msg->N_bits * 8 + 8 + 16);
M[0] = (count >> 24) & 0xFF;
M[1] = (count >> 16) & 0xFF;
M[2] = (count >> 8) & 0xFF;
M[3] = count & 0xFF;
M[4] = (bearer << 3) | (direction << 2);
for (i = 0; i < msg->N_bits / 8; i++) {
M[8 + i] = 0;
for (j = 0; j < 8; j++) {
M[8 + i] |= msg->msg[i * 8 + j] << (7 - j);
}
}
if ((msg->N_bits % 8) != 0) {
M[8 + i] = 0;
for (j = 0; j < msg->N_bits % 8; j++) {
M[8 + i] |= msg->msg[i * 8 + j] << (7 - j);
}
}
// MAC generation
n = (uint32)(ceilf((float)(msg->N_bits + 64) / (float)(128)));
for (i = 0; i < 16; i++) {
T[i] = 0;
}
for (i = 0; i < n - 1; i++) {
for (j = 0; j < 16; j++) {
tmp[j] = T[j] ^ M[i * 16 + j];
}
aes_crypt_ecb(&ctx, AES_ENCRYPT, tmp, T);
}
pad_bits = (msg->N_bits + 64) % 128;
if (pad_bits == 0) {
for (j = 0; j < 16; j++) {
tmp[j] = T[j] ^ K1[j] ^ M[i * 16 + j];
}
aes_crypt_ecb(&ctx, AES_ENCRYPT, tmp, T);
} else {
pad_bits = (128 - pad_bits) - 1;
M[i * 16 + (15 - (pad_bits / 8))] |= 0x1 << (pad_bits % 8);
for (j = 0; j < 16; j++) {
tmp[j] = T[j] ^ K2[j] ^ M[i * 16 + j];
}
aes_crypt_ecb(&ctx, AES_ENCRYPT, tmp, T);
}
for (i = 0; i < 4; i++) {
mac[i] = T[i];
}
return LIBLTE_SUCCESS;
}
uint32_t GET_WORD(uint32_t* DATA, uint32_t i)
{
uint32_t WORD, ti;
ti = i % 32;
if (ti == 0)
WORD = DATA[i / 32];
else
WORD = (DATA[i / 32] << ti) | (DATA[i / 32 + 1] >> (32 - ti));
return WORD;
}
uint8_t GET_BIT(uint8_t* DATA, uint32_t i)
{
return (DATA[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
}
LIBLTE_ERROR_ENUM liblte_security_128_eia3(const uint8* key,
uint32 count,
uint8 bearer,
uint8 direction,
uint8* msg,
uint32 msg_len,
uint8* mac)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8_t iv[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint32* ks;
uint32 msg_len_block_8, msg_len_block_32, m;
if (key != NULL && msg != NULL && mac != NULL) {
msg_len_block_8 = (msg_len + 7) / 8;
msg_len_block_32 = (msg_len + 31) / 32;
// Construct iv
iv[0] = (count >> 24) & 0xFF;
iv[1] = (count >> 16) & 0xFF;
iv[2] = (count >> 8) & 0xFF;
iv[3] = count & 0xFF;
iv[4] = (bearer << 3) & 0xF8;
iv[5] = iv[6] = iv[7] = 0;
iv[8] = ((count >> 24) & 0xFF) ^ ((direction & 1) << 7);
iv[9] = (count >> 16) & 0xFF;
iv[10] = (count >> 8) & 0xFF;
iv[11] = count & 0xFF;
iv[12] = iv[4];
iv[13] = iv[5];
iv[14] = iv[6] ^ ((direction & 1) << 7);
iv[15] = iv[7];
zuc_state_t zuc_state;
// Initialize keystream
zuc_initialize(&zuc_state, key, iv);
// Generate keystream
int N = msg_len + 64;
int L = (N + 31) / 32;
ks = (uint32*)calloc(L, sizeof(uint32));
zuc_generate_keystream(&zuc_state, L, ks);
uint32_t T = 0;
for (uint32_t i = 0; i < msg_len; i++) {
if (GET_BIT(msg, i)) {
T ^= GET_WORD(ks, i);
}
}
T ^= GET_WORD(ks, msg_len);
uint32_t mac_tmp = T ^ ks[L - 1];
mac[0] = (mac_tmp >> 24) & 0xFF;
mac[1] = (mac_tmp >> 16) & 0xFF;
mac[2] = (mac_tmp >> 8) & 0xFF;
mac[3] = mac_tmp & 0xFF;
free(ks);
}
return (err);
}
/*********************************************************************
Name: liblte_security_encryption_eea1
Description: 128-bit encryption algorithm EEA1.
Document Reference: 33.401 v13.1.0 Annex B.1.2
35.215 v13.0.0 References
Specification of the 3GPP Confidentiality and
Integrity Algorithms UEA2 & UIA2 D1 v2.1
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_encryption_eea1(uint8* key,
uint32 count,
uint8 bearer,
uint8 direction,
uint8* msg,
uint32 msg_len,
uint8* out)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
S3G_STATE state, *state_ptr;
uint32 k[] = {0, 0, 0, 0};
uint32 iv[] = {0, 0, 0, 0};
uint32* ks;
int32 i;
uint32 msg_len_block_8, msg_len_block_32, m;
if (key != NULL && msg != NULL && out != NULL) {
state_ptr = &state;
msg_len_block_8 = (msg_len + 7) / 8;
msg_len_block_32 = (msg_len + 31) / 32;
// Transform key
for (i = 3; i >= 0; i--) {
k[i] = (key[4 * (3 - i) + 0] << 24) | (key[4 * (3 - i) + 1] << 16) | (key[4 * (3 - i) + 2] << 8) |
(key[4 * (3 - i) + 3]);
}
// Construct iv
iv[3] = count;
iv[2] = ((bearer & 0x1F) << 27) | ((direction & 0x01) << 26);
iv[1] = iv[3];
iv[0] = iv[2];
// Initialize keystream
s3g_initialize(state_ptr, k, iv);
// Generate keystream
ks = (uint32*)calloc(msg_len_block_32, sizeof(uint32));
s3g_generate_keystream(state_ptr, msg_len_block_32, ks);
// Generate output except last block
for (i = 0; i < (int32_t)msg_len_block_32 - 1; i++) {
out[4 * i + 0] = msg[4 * i + 0] ^ ((ks[i] >> 24) & 0xFF);
out[4 * i + 1] = msg[4 * i + 1] ^ ((ks[i] >> 16) & 0xFF);
out[4 * i + 2] = msg[4 * i + 2] ^ ((ks[i] >> 8) & 0xFF);
out[4 * i + 3] = msg[4 * i + 3] ^ ((ks[i] & 0xFF));
}
// Process last bytes
for (i = (msg_len_block_32 - 1) * 4; i < (int32_t)msg_len_block_8; i++) {
out[i] = msg[i] ^ ((ks[i / 4] >> ((3 - (i % 4)) * 8)) & 0xFF);
}
// Zero tailing bits
zero_tailing_bits(out, msg_len);
// Clean up
free(ks);
s3g_deinitialize(state_ptr);
err = LIBLTE_SUCCESS;
}
return (err);
}
/*********************************************************************
Name: liblte_security_decryption_eea1
Description: 128-bit decryption algorithm EEA1.
Document Reference: 33.401 v13.1.0 Annex B.1.2
35.215 v13.0.0 References
Specification of the 3GPP Confidentiality and
Integrity Algorithms UEA2 & UIA2 D1 v2.1
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_decryption_eea1(uint8* key,
uint32 count,
uint8 bearer,
uint8 direction,
uint8* ct,
uint32 ct_len,
uint8* out)
{
return liblte_security_encryption_eea1(key, count, bearer, direction, ct, ct_len, out);
}
/*********************************************************************
Name: liblte_security_encryption_eea2
Description: 128-bit encryption algorithm EEA2.
Document Reference: 33.401 v13.1.0 Annex B.1.3
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_encryption_eea2(uint8* key,
uint32 count,
uint8 bearer,
uint8 direction,
uint8* msg,
uint32 msg_len,
uint8* out)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
aes_context ctx;
unsigned char stream_blk[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char nonce_cnt[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int32 i;
int ret;
size_t nc_off = 0;
if (key != NULL && msg != NULL && out != NULL) {
ret = aes_setkey_enc(&ctx, key, 128);
if (ret == 0) {
// Construct nonce
nonce_cnt[0] = (count >> 24) & 0xFF;
nonce_cnt[1] = (count >> 16) & 0xFF;
nonce_cnt[2] = (count >> 8) & 0xFF;
nonce_cnt[3] = (count)&0xFF;
nonce_cnt[4] = ((bearer & 0x1F) << 3) | ((direction & 0x01) << 2);
// Encryption
ret = aes_crypt_ctr(&ctx, (msg_len + 7) / 8, &nc_off, nonce_cnt, stream_blk, msg, out);
}
if (ret == 0) {
// Zero tailing bits
zero_tailing_bits(out, msg_len);
err = LIBLTE_SUCCESS;
}
}
return (err);
}
/*********************************************************************
Name: liblte_security_decryption_eea2
Description: 128-bit decryption algorithm EEA2.
Document Reference: 33.401 v13.1.0 Annex B.1.3
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_decryption_eea2(uint8* key,
uint32 count,
uint8 bearer,
uint8 direction,
uint8* ct,
uint32 ct_len,
uint8* out)
{
return liblte_security_encryption_eea2(key, count, bearer, direction, ct, ct_len, out);
}
/*********************************************************************
Name: liblte_security_encryption_eea1
Description: 128-bit encryption algorithm EEA1.
Document Reference: 33.401 v13.1.0 Annex B.1.2
35.215 v13.0.0 References
Specification of the 3GPP Confidentiality and
Integrity Algorithms UEA2 & UIA2 D1 v2.1
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_encryption_eea3(uint8* key,
uint32 count,
uint8 bearer,
uint8 direction,
uint8* msg,
uint32 msg_len,
uint8* out)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint8_t iv[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint32* ks;
int32 i;
uint32 msg_len_block_8, msg_len_block_32, m;
if (key != NULL && msg != NULL && out != NULL) {
msg_len_block_8 = (msg_len + 7) / 8;
msg_len_block_32 = (msg_len + 31) / 32;
// Construct iv
iv[0] = (count >> 24) & 0xFF;
iv[1] = (count >> 16) & 0xFF;
iv[2] = (count >> 8) & 0xFF;
iv[3] = (count)&0xFF;
iv[4] = ((bearer & 0x1F) << 3) | ((direction & 0x01) << 2);
iv[5] = 0;
iv[6] = 0;
iv[7] = 0;
iv[8] = iv[0];
iv[9] = iv[1];
iv[10] = iv[2];
iv[11] = iv[3];
iv[12] = iv[4];
iv[13] = iv[5];
iv[14] = iv[6];
iv[15] = iv[7];
zuc_state_t zuc_state;
// Initialize keystream
zuc_initialize(&zuc_state, key, iv);
// Generate keystream
ks = (uint32*)calloc(msg_len_block_32, sizeof(uint32));
zuc_generate_keystream(&zuc_state, msg_len_block_32, ks);
// Generate output except last block
for (i = 0; i < (int32_t)msg_len_block_32 - 1; i++) {
out[4 * i + 0] = msg[4 * i + 0] ^ ((ks[i] >> 24) & 0xFF);
out[4 * i + 1] = msg[4 * i + 1] ^ ((ks[i] >> 16) & 0xFF);
out[4 * i + 2] = msg[4 * i + 2] ^ ((ks[i] >> 8) & 0xFF);
out[4 * i + 3] = msg[4 * i + 3] ^ ((ks[i] & 0xFF));
}
// Process last bytes
for (i = (msg_len_block_32 - 1) * 4; i < (int32_t)msg_len_block_8; i++) {
out[i] = msg[i] ^ ((ks[i / 4] >> ((3 - (i % 4)) * 8)) & 0xFF);
}
// Zero tailing bits
zero_tailing_bits(out, msg_len);
// Clean up
free(ks);
// zuc_deinitialize(state_ptr);
err = LIBLTE_SUCCESS;
}
return (err);
}
LIBLTE_ERROR_ENUM liblte_security_decryption_eea3(uint8* key,
uint32 count,
uint8 bearer,
uint8 direction,
uint8* msg,
uint32 msg_len,
uint8* out)
{
return liblte_security_encryption_eea3(key, count, bearer, direction, msg, msg_len, out);
}
/*********************************************************************
Name: liblte_security_milenage_f1
Description: Milenage security function F1. Computes network
authentication code MAC-A from key K, random
challenge RAND, sequence number SQN, and
authentication management field AMF.
Document Reference: 35.206 v10.0.0 Annex 3
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_milenage_f1(uint8* k, uint8* op_c, uint8* rand, uint8* sqn, uint8* amf, uint8* mac_a)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint32 i;
aes_context ctx;
uint8 temp[16];
uint8 in1[16];
uint8 out1[16];
uint8 input[16];
if (k != NULL && op_c != NULL && rand != NULL && sqn != NULL && amf != NULL && mac_a != NULL) {
// Initialize the round keys
aes_setkey_enc(&ctx, k, 128);
// Compute temp
for (i = 0; i < 16; i++) {
input[i] = rand[i] ^ op_c[i];
}
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, temp);
// Construct in1
for (i = 0; i < 6; i++) {
in1[i] = sqn[i];
in1[i + 8] = sqn[i];
}
for (i = 0; i < 2; i++) {
in1[i + 6] = amf[i];
in1[i + 14] = amf[i];
}
// Compute out1
for (i = 0; i < 16; i++) {
input[(i + 8) % 16] = in1[i] ^ op_c[i];
}
for (i = 0; i < 16; i++) {
input[i] ^= temp[i];
}
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out1);
for (i = 0; i < 16; i++) {
out1[i] ^= op_c[i];
}
// Return MAC-A
for (i = 0; i < 8; i++) {
mac_a[i] = out1[i];
}
err = LIBLTE_SUCCESS;
}
return (err);
}
/*********************************************************************
Name: liblte_security_milenage_f1_star
Description: Milenage security function F1*. Computes resynch
authentication code MAC-S from key K, random
challenge RAND, sequence number SQN, and
authentication management field AMF.
Document Reference: 35.206 v10.0.0 Annex 3
*********************************************************************/
LIBLTE_ERROR_ENUM
liblte_security_milenage_f1_star(uint8* k, uint8* op_c, uint8* rand, uint8* sqn, uint8* amf, uint8* mac_s)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
aes_context ctx;
uint32 i;
uint8 temp[16];
uint8 in1[16];
uint8 out1[16];
uint8 input[16];
if (k != NULL && op_c != NULL && rand != NULL && sqn != NULL && amf != NULL && mac_s != NULL) {
// Initialize the round keys
aes_setkey_enc(&ctx, k, 128);
// Compute temp
for (i = 0; i < 16; i++) {
input[i] = rand[i] ^ op_c[i];
}
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, temp);
// Construct in1
for (i = 0; i < 6; i++) {
in1[i] = sqn[i];
in1[i + 8] = sqn[i];
}
for (i = 0; i < 2; i++) {
in1[i + 6] = amf[i];
in1[i + 14] = amf[i];
}
// Compute out1
for (i = 0; i < 16; i++) {
input[(i + 8) % 16] = in1[i] ^ op_c[i];
}
for (i = 0; i < 16; i++) {
input[i] ^= temp[i];
}
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out1);
for (i = 0; i < 16; i++) {
out1[i] ^= op_c[i];
}
// Return MAC-S
for (i = 0; i < 8; i++) {
mac_s[i] = out1[i + 8];
}
err = LIBLTE_SUCCESS;
}
return (err);
}
/*********************************************************************
Name: liblte_security_milenage_f2345
Description: Milenage security functions F2, F3, F4, and F5.
Computes response RES, confidentiality key CK,
integrity key IK, and anonymity key AK from random
challenge RAND.
Document Reference: 35.206 v10.0.0 Annex 3
*********************************************************************/
LIBLTE_ERROR_ENUM
liblte_security_milenage_f2345(uint8* k, uint8* op_c, uint8* rand, uint8* res, uint8* ck, uint8* ik, uint8* ak)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
uint32 i;
uint8 temp[16];
uint8 out[16];
uint8 input[16];
aes_context ctx;
if (k != NULL && op_c != NULL && rand != NULL && res != NULL && ck != NULL && ik != NULL && ak != NULL) {
// Initialize the round keys
aes_setkey_enc(&ctx, k, 128);
// Compute temp
for (i = 0; i < 16; i++) {
input[i] = rand[i] ^ op_c[i];
}
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, temp);
// Compute out for RES and AK
for (i = 0; i < 16; i++) {
input[i] = temp[i] ^ op_c[i];
}
input[15] ^= 1;
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out);
for (i = 0; i < 16; i++) {
out[i] ^= op_c[i];
}
// Return RES
for (i = 0; i < 8; i++) {
res[i] = out[i + 8];
}
// Return AK
for (i = 0; i < 6; i++) {
ak[i] = out[i];
}
// Compute out for CK
for (i = 0; i < 16; i++) {
input[(i + 12) % 16] = temp[i] ^ op_c[i];
}
input[15] ^= 2;
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out);
for (i = 0; i < 16; i++) {
out[i] ^= op_c[i];
}
// Return CK
for (i = 0; i < 16; i++) {
ck[i] = out[i];
}
// Compute out for IK
for (i = 0; i < 16; i++) {
input[(i + 8) % 16] = temp[i] ^ op_c[i];
}
input[15] ^= 4;
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out);
for (i = 0; i < 16; i++) {
out[i] ^= op_c[i];
}
// Return IK
for (i = 0; i < 16; i++) {
ik[i] = out[i];
}
err = LIBLTE_SUCCESS;
}
return (err);
}
/*********************************************************************
Name: liblte_security_milenage_f5_star
Description: Milenage security function F5*. Computes resynch
anonymity key AK from key K and random challenge
RAND.
Document Reference: 35.206 v10.0.0 Annex 3
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_security_milenage_f5_star(uint8* k, uint8* op_c, uint8* rand, uint8* ak)
{
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
aes_context ctx;
uint32 i;
uint8 temp[16];
uint8 out[16];
uint8 input[16];
if (k != NULL && op_c != NULL && rand != NULL && ak != NULL) {
// Initialize the round keys
aes_setkey_enc(&ctx, k, 128);
// Compute temp
for (i = 0; i < 16; i++) {
input[i] = rand[i] ^ op_c[i];
}
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, temp);
// Compute out
for (i = 0; i < 16; i++) {
input[(i + 4) % 16] = temp[i] ^ op_c[i];
}
input[15] ^= 8;
aes_crypt_ecb(&ctx, AES_ENCRYPT, input, out);
for (i = 0; i < 16; i++) {
out[i] ^= op_c[i];
}
// Return AK
for (i = 0; i < 6; i++) {
ak[i] = out[i];
}
err = LIBLTE_SUCCESS;
}
return (err);
}
/*********************************************************************
Name: liblte_compute_opc
Description: Computes OPc from OP and K.
Document Reference: 35.206 v10.0.0 Annex 3
*********************************************************************/
LIBLTE_ERROR_ENUM liblte_compute_opc(uint8* k, uint8* op, uint8* op_c)
{
uint32 i;
aes_context ctx;
LIBLTE_ERROR_ENUM err = LIBLTE_ERROR_INVALID_INPUTS;
if (k != NULL && op != NULL && op_c != NULL) {
aes_setkey_enc(&ctx, k, 128);
aes_crypt_ecb(&ctx, AES_ENCRYPT, op, op_c);
for (i = 0; i < 16; i++) {
op_c[i] ^= op[i];
}
err = LIBLTE_SUCCESS;
}
return err;
}
/*********************************************************************
Name: zero_tailing_bits
Description: Fill tailing bits with zeros.
Document Reference: -
*********************************************************************/
void zero_tailing_bits(uint8* data, uint32 length_bits)
{
uint8 bits = (8 - (length_bits & 0x07)) & 0x07;
data[(length_bits + 7) / 8 - 1] &= (uint8)(0xFF << bits);
}