mirror of https://github.com/PentHertz/srsLTE.git
1358 lines
42 KiB
C++
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);
|
|
}
|