Commit 97a3fa35 authored by Yann Garcia's avatar Yann Garcia
Browse files

Validating integrity protection with ZUC

parent 01aa2349
Loading
Loading
Loading
Loading
+183 −119

File changed.

Preview size limit exceeded, changes collapsed.

+134 −90
Original line number Diff line number Diff line
@@ -23,28 +23,28 @@ namespace {
    constexpr size_t IV_SIZE = 16;   // Initialization vector size
}

uint32_t ia3_128::LFSR_S0  = 0;
uint32_t ia3_128::LFSR_S1  = 0;
uint32_t ia3_128::LFSR_S2  = 0;
uint32_t ia3_128::LFSR_S3  = 0;
uint32_t ia3_128::LFSR_S4  = 0;
uint32_t ia3_128::LFSR_S5  = 0;
uint32_t ia3_128::LFSR_S6  = 0;
uint32_t ia3_128::LFSR_S7  = 0;
uint32_t ia3_128::LFSR_S8  = 0;
uint32_t ia3_128::LFSR_S9  = 0;
uint32_t ia3_128::LFSR_S10 = 0;
uint32_t ia3_128::LFSR_S11 = 0;
uint32_t ia3_128::LFSR_S12 = 0;
uint32_t ia3_128::LFSR_S13 = 0;
uint32_t ia3_128::LFSR_S14 = 0;
uint32_t ia3_128::LFSR_S15 = 0;
uint32_t ia3_128::F_R1     = 0;
uint32_t ia3_128::F_R2     = 0;
uint32_t ia3_128::BRC_X0   = 0;
uint32_t ia3_128::BRC_X1   = 0;
uint32_t ia3_128::BRC_X2   = 0;
uint32_t ia3_128::BRC_X3   = 0;
uint32_t ia3_128::lfsr_s0  = 0;
uint32_t ia3_128::lfsr_s1  = 0;
uint32_t ia3_128::lfsr_s2  = 0;
uint32_t ia3_128::lfsr_s3  = 0;
uint32_t ia3_128::lfsr_s4  = 0;
uint32_t ia3_128::lfsr_s5  = 0;
uint32_t ia3_128::lfsr_s6  = 0;
uint32_t ia3_128::lfsr_s7  = 0;
uint32_t ia3_128::lfsr_s8  = 0;
uint32_t ia3_128::lfsr_s9  = 0;
uint32_t ia3_128::lfsr_s10 = 0;
uint32_t ia3_128::lfsr_s11 = 0;
uint32_t ia3_128::lfsr_s12 = 0;
uint32_t ia3_128::lfsr_s13 = 0;
uint32_t ia3_128::lfsr_s14 = 0;
uint32_t ia3_128::lfsr_s15 = 0;
uint32_t ia3_128::f_r1     = 0;
uint32_t ia3_128::f_r2     = 0;
uint32_t ia3_128::brc_x0   = 0;
uint32_t ia3_128::brc_x1   = 0;
uint32_t ia3_128::brc_x2   = 0;
uint32_t ia3_128::brc_x3   = 0;

int ia3_128::encrypt(const uint8_t algo_id,
                     const unsigned char* knas_enc,
@@ -105,103 +105,147 @@ int ia3_128::decrypt(const uint8_t algo_id,
                   cyphered, cyphered_length, payload, payload_length);
}

void ia3_128::zuc_eea3(const uint8_t* CK, const uint32_t COUNT, const uint32_t BEARER, const uint32_t DIRECTION, const uint32_t LENGTH, const uint8_t* M, uint8_t* C) {
  loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: knas_enc", CK, KEY_SIZE);
  loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: payload", M, LENGTH / 8);
  loggers::get_instance().log(">>> ia3_128::zuc_eea3: count: %u", COUNT);
  loggers::get_instance().log(">>> ia3_128::zuc_eea3: bearer: %d", BEARER);
  loggers::get_instance().log(">>> ia3_128::zuc_eea3: direction: %d", DIRECTION);
int ia3_128::mac(const uint8_t algo_id,
                     const unsigned char* knas_int,
                     const uint32_t count,
                     const uint8_t bearer,
                     const uint8_t direction,
                     const unsigned char* payload,
                     const uint32_t payload_length,
                     unsigned char** mac,
                     uint32_t* mac_length) {
  loggers::get_instance().log_to_hexa(">>> ia3_128::mac: knas_int", knas_int, KEY_SIZE);
  loggers::get_instance().log(">>> ia3_128::mac: payload_length: %d", payload_length);
  loggers::get_instance().log_to_hexa(">>> ia3_128::mac: payload", payload, payload_length);
  loggers::get_instance().log(">>> ia3_128::mac: algo_id: %d", algo_id);
  loggers::get_instance().log(">>> ia3_128::mac: count: %u", count);
  loggers::get_instance().log(">>> ia3_128::mac: bearer: %d", bearer);
  loggers::get_instance().log(">>> ia3_128::mac: direction: %d", direction);

  // Input validation
  if (!knas_int || !payload || !mac || !mac_length) {
    loggers::get_instance().error("ia3_128::mac: Wrong input parameters");
    return -1;
  }

  if (payload_length == 0) {
    loggers::get_instance().error("ia3_128::mac: Wrong payload length");
    *mac = nullptr;
    *mac_length = 0;
    return 0;
  }

  uint32_t *z, L, L8, i;
  uint8_t 	IV[KEY_SIZE];
  uint32_t lastbits = (8-(LENGTH%8))%8;
  // Allocate memory for ciphertext
  *mac = static_cast<unsigned char*>(std::malloc(4));
  if (!*mac) {
    loggers::get_instance().error("ia3_128::mac: Failed to allocate memory");
    return -1;
  }
  *mac_length = 4;
  uint32_t wmac = 0;
  zuc_eia3(knas_int, count, bearer, direction, payload_length * 8, payload, &wmac);
  (*mac)[0] = (wmac >> 24) & 0xFF;
  (*mac)[1] = (wmac >> 16) & 0xFF;
  (*mac)[2] = (wmac >> 8) & 0xFF;
  (*mac)[3] = wmac & 0xFF;
  loggers::get_instance().log_to_hexa("ia3_128::mac: mac: ", *mac, *mac_length);

  loggers::get_instance().log("<<< ia3_128::mac: ret: 0");
  return 0;
}

  L 	= (LENGTH+31)/32;
  z	= static_cast<uint32_t*>(std::malloc(L*sizeof(uint32_t)));
void ia3_128::zuc_eea3(const uint8_t* p_knas_enc, const uint32_t count, const uint32_t bearer, const uint32_t direction, const uint32_t payload_length, const uint8_t* payload, uint8_t* ciphered) {
  loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: knas_enc", p_knas_enc, KEY_SIZE);
  loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: payload", payload, payload_length / 8);
  loggers::get_instance().log(">>> ia3_128::zuc_eea3: count: %u", count);
  loggers::get_instance().log(">>> ia3_128::zuc_eea3: bearer: %d", bearer);
  loggers::get_instance().log(">>> ia3_128::zuc_eea3: direction: %d", direction);

  uint32_t *z, lenght, lenght_in_bytes, i;
  uint8_t 	iv[KEY_SIZE];
  uint32_t lastbits = (8-(payload_length%8))%8;
  
  L8 	= (LENGTH+7)/8;
  lenght 	= (payload_length+31)/32;
  z	= static_cast<uint32_t*>(std::malloc(lenght*sizeof(uint32_t)));
  
  IV[0]	= (COUNT>>24) & 0xFF;
  IV[1]	= (COUNT>>16) & 0xFF;
  IV[2]	= (COUNT>>8)  & 0xFF;
  IV[3]	=  COUNT      & 0xFF;
  
  IV[4]	= ((BEARER << 3) | ((DIRECTION&1)<<2)) & 0xFC;
  IV[5]	= 0;
  IV[6]	= 0;
  IV[7]	= 0;
  lenght_in_bytes 	= (payload_length+7)/8;
  
  IV[8]	= IV[0];
  IV[9]	= IV[1];
  IV[10]	= IV[2];
  IV[11]	= IV[3];
  iv[0]	= (count>>24) & 0xFF;
  iv[1]	= (count>>16) & 0xFF;
  iv[2]	= (count>>8)  & 0xFF;
  iv[3]	=  count      & 0xFF;
  
  IV[12]	= IV[4];
  IV[13]	= IV[5];
  IV[14]	= IV[6];
  IV[15]	= IV[7];
  loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: IV", IV, KEY_SIZE);
  iv[4]	= ((bearer << 3) | ((direction&1)<<2)) & 0xFC;
  iv[5]	= 0;
  iv[6]	= 0;
  iv[7]	= 0;
  
  ZUC(CK, IV, z, L);
  loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: z", (uint8_t*)z, L*sizeof(uint32_t));
  iv[8]	= iv[0];
  iv[9]	= iv[1];
  iv[10]	= iv[2];
  iv[11]	= iv[3];
  
  for (i=0; i<L8; i++) {
      C[i] = M[i] ^ ((z[i/4] >> (3-i%4)*8) & 0xff);
  }
  iv[12]	= iv[4];
  iv[13]	= iv[5];
  iv[14]	= iv[6];
  iv[15]	= iv[7];
  loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: iv", iv, KEY_SIZE);
  
  /*
  * Issues #3349
  * Valgrind memcheck: Invalid read & write: Add {}.
  */
  zuc(p_knas_enc, iv, z, lenght);
  loggers::get_instance().log_to_hexa(">>> ia3_128::zuc_eea3: z", (uint8_t*)z, lenght*sizeof(uint32_t));
  
  for (i=0; i<lenght_in_bytes; i++) {
    ciphered[i] = payload[i] ^ ((z[i/4] >> (3-i%4)*8) & 0xff);
  }

  /* zero last bits of data in case its length is not  word-aligned (32 bits)
  this is an addition to the C reference code, which did not handle it */
  this is an addition to the ciphered reference code, which did not handle it */
  if (lastbits) {
    i--;
      C[i] &= 0x100 - (1<<lastbits);
    ciphered[i] &= 0x100 - (1<<lastbits);
  }
  loggers::get_instance().log_to_hexa("ia3_128::zuc_eea3: C", C, LENGTH / 8);
  loggers::get_instance().log_to_hexa("ia3_128::zuc_eea3: ciphered", ciphered, payload_length / 8);

  std::free(z);
}

void ia3_128::zuc_eia3(const uint8_t* IK, const uint32_t COUNT, const uint32_t BEARER, const uint32_t DIRECTION, const uint32_t LENGTH, const uint8_t* M, uint32_t* MAC) {
  uint32_t	*z, N, L, T, i;
  uint8_t IV[16];
void ia3_128::zuc_eia3(const uint8_t* p_knas_int, const uint32_t count, const uint32_t bearer, const uint32_t direction, const uint32_t payload_length, const uint8_t* payload, uint32_t* mac) {
  uint32_t	*z, N, lenght, T, i;
  uint8_t iv[16];

  IV[0]	= (COUNT>>24) & 0xFF;
  IV[1]	= (COUNT>>16) & 0xFF;
  IV[2]	= (COUNT>>8) & 0xFF;
  IV[3]	= COUNT & 0xFF;
  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[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[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];
  iv[12]	= iv[4];
  iv[13]	= iv[5];
  iv[14]	= iv[6] ^ ((direction&1)<<7);
  iv[15]	= iv[7];
  
  N	= LENGTH + 64;
  L	= (N + 31) / 32;
  z	= static_cast<uint32_t*>(std::malloc(L*sizeof(uint32_t)));
  N	= payload_length + 64;
  lenght	= (N + 31) / 32;
  z	= static_cast<uint32_t*>(std::malloc(lenght*sizeof(uint32_t)));
  
  ZUC(IK, IV, z, L);
  zuc(p_knas_int, iv, z, lenght);
  
  T = 0;
  for (i=0; i<LENGTH; i++) {
      if (GET_BIT(M,i)) {
          T ^= GET_WORD(z,i);
  for (i=0; i<payload_length; i++) {
      if (get_bit(payload,i)) {
          T ^= get_word(z,i);
      }
  }
  T ^= GET_WORD(z,LENGTH);
  T ^= get_word(z,payload_length);
  
  *MAC = T ^ z[L-1];
  *mac = T ^ z[lenght-1];
  std::free(z);
}
+164 −135
Original line number Diff line number Diff line
@@ -114,8 +114,37 @@ public:
                unsigned char** payload,  
                uint32_t* payload_length);

    /**
     * @brief Compute NAS integrity protection using ZUC algorithm
     * 
     * This method computes the  integrity protection using the ZUC stream cipher.
     * 
     * @param algo_id Algorithm identifier (should be 3 for ZUC)
     * @param knas_enc Pointer to the 16-byte NAS encryption key
     * @param count 32-bit NAS count value
     * @param bearer 5-bit bearer identifier (only lower 5 bits are used)
     * @param direction Direction bit (0 = uplink, 1 = downlink)
     * @param cyphered Pointer to the ciphertext data to decrypt
     * @param cyphered_length Length of the ciphertext data in bytes
     * @param payload Pointer to pointer that will receive the decrypted data (caller must free)
     * @param payload_length Pointer to variable that will receive the decrypted data length
     * @return 0 on success, negative value on error
     * 
     * @note The caller is responsible for freeing the memory allocated for payload
     * @note payload_length will be equal to cyphered_length for stream ciphers
     */
    int mac(const uint8_t algo_id, 
            const unsigned char* knas_int, 
            const uint32_t count, 
            const uint8_t bearer, 
            const uint8_t direction, 
            const unsigned char* payload, 
            const uint32_t payload_length, 
            unsigned char** cyphered, 
            uint32_t* cyphered_length);

private:
  const uint8_t  S0[256] = {
  const uint8_t s0[256] = {
    0x3e,0x72,0x5b,0x47,0xca,0xe0,0x00,0x33,0x04,0xd1,0x54,0x98,0x09,0xb9,0x6d,0xcb,
    0x7b,0x1b,0xf9,0x32,0xaf,0x9d,0x6a,0xa5,0xb8,0x2d,0xfc,0x1d,0x08,0x53,0x03,0x90,
    0x4d,0x4e,0x84,0x99,0xe4,0xce,0xd9,0x91,0xdd,0xb6,0x85,0x48,0x8b,0x29,0x6e,0xac,
@@ -134,7 +163,7 @@ private:
    0x8d,0x27,0x1a,0xdb,0x81,0xb3,0xa0,0xf4,0x45,0x7a,0x19,0xdf,0xee,0x78,0x34,0x60
  }; 

  const uint8_t S1[256] =  {
  const uint8_t s1[256] =  {
    0x55,0xc2,0x63,0x71,0x3b,0xc8,0x47,0x86,0x9f,0x3c,0xda,0x5b,0x29,0xaa,0xfd,0x77,
    0x8c,0xc5,0x94,0x0c,0xa6,0x1a,0x13,0x00,0xe3,0xa8,0x16,0x72,0x40,0xf9,0xf8,0x42,
    0x44,0x26,0x68,0x96,0x81,0xd9,0x45,0x3e,0x10,0x76,0xc6,0xa7,0x8b,0x39,0x43,0xe1,
@@ -160,32 +189,32 @@ private:
  };

  /* the state registers of LFSR */ 
  static uint32_t LFSR_S0;
  static uint32_t LFSR_S1;
  static uint32_t LFSR_S2;
  static uint32_t LFSR_S3;
  static uint32_t LFSR_S4;
  static uint32_t LFSR_S5;
  static uint32_t LFSR_S6;
  static uint32_t LFSR_S7;
  static uint32_t LFSR_S8;
  static uint32_t LFSR_S9;
  static uint32_t LFSR_S10;
  static uint32_t LFSR_S11;
  static uint32_t LFSR_S12;
  static uint32_t LFSR_S13;
  static uint32_t LFSR_S14;
  static uint32_t LFSR_S15;
  static uint32_t lfsr_s0;
  static uint32_t lfsr_s1;
  static uint32_t lfsr_s2;
  static uint32_t lfsr_s3;
  static uint32_t lfsr_s4;
  static uint32_t lfsr_s5;
  static uint32_t lfsr_s6;
  static uint32_t lfsr_s7;
  static uint32_t lfsr_s8;
  static uint32_t lfsr_s9;
  static uint32_t lfsr_s10;
  static uint32_t lfsr_s11;
  static uint32_t lfsr_s12;
  static uint32_t lfsr_s13;
  static uint32_t lfsr_s14;
  static uint32_t lfsr_s15;

  /* the registers of F */
  static uint32_t F_R1;
  static uint32_t F_R2;
  static uint32_t f_r1;
  static uint32_t f_r2;

  /* the outputs of BitReorganization */
  static uint32_t BRC_X0;
  static uint32_t BRC_X1;
  static uint32_t BRC_X2;
  static uint32_t BRC_X3;
  /* the outputs of bit_reorganization */
  static uint32_t brc_x0;
  static uint32_t brc_x1;
  static uint32_t brc_x2;
  static uint32_t brc_x3;

  /* c = a + b mod (2^31 - 1) */
  inline uint32_t AddM(uint32_t a, uint32_t b) {
@@ -195,83 +224,83 @@ private:

  /* LFSR with initialization mode */
  #define MulByPow2(x, k) ((((x) << k) | ((x) >> (31 - k))) & 0x7FFFFFFF)
  inline void LFSRWithInitialisationMode(uint32_t u) {
  inline void lfsr_with_initialisation_mode(uint32_t u) {
    uint32_t f, v;
    f = LFSR_S0;
    f = lfsr_s0;
    
    v = MulByPow2(LFSR_S0, 8);
    v = MulByPow2(lfsr_s0, 8);
    f = AddM(f, v);
    v = MulByPow2(LFSR_S4, 20);
    v = MulByPow2(lfsr_s4, 20);
    f = AddM(f, v);
    v = MulByPow2(LFSR_S10, 21);
    v = MulByPow2(lfsr_s10, 21);
    f = AddM(f, v);
    v = MulByPow2(LFSR_S13, 17);
    v = MulByPow2(lfsr_s13, 17);
    f = AddM(f, v);
    v = MulByPow2(LFSR_S15, 15);
    v = MulByPow2(lfsr_s15, 15);
    f = AddM(f, v);
    
    f = AddM(f, u);
    
    /* update the state */
    LFSR_S0 = LFSR_S1;
    LFSR_S1 = LFSR_S2;
    LFSR_S2 = LFSR_S3;
    LFSR_S3 = LFSR_S4;
    LFSR_S4 = LFSR_S5;
    LFSR_S5 = LFSR_S6;
    LFSR_S6 = LFSR_S7;
    LFSR_S7 = LFSR_S8;
    LFSR_S8 = LFSR_S9;
    LFSR_S9 = LFSR_S10;
    LFSR_S10 = LFSR_S11;
    LFSR_S11 = LFSR_S12;
    LFSR_S12 = LFSR_S13;
    LFSR_S13 = LFSR_S14;
    LFSR_S14 = LFSR_S15;
    LFSR_S15 = f;
    lfsr_s0 = lfsr_s1;
    lfsr_s1 = lfsr_s2;
    lfsr_s2 = lfsr_s3;
    lfsr_s3 = lfsr_s4;
    lfsr_s4 = lfsr_s5;
    lfsr_s5 = lfsr_s6;
    lfsr_s6 = lfsr_s7;
    lfsr_s7 = lfsr_s8;
    lfsr_s8 = lfsr_s9;
    lfsr_s9 = lfsr_s10;
    lfsr_s10 = lfsr_s11;
    lfsr_s11 = lfsr_s12;
    lfsr_s12 = lfsr_s13;
    lfsr_s13 = lfsr_s14;
    lfsr_s14 = lfsr_s15;
    lfsr_s15 = f;
  };

  /* LFSR with work mode */
  inline void LFSRWithWorkMode(void) {
  inline void lfsr_with_work_mode(void) {
    uint32_t f, v;
    f = LFSR_S0;
    f = lfsr_s0;
    
    v = MulByPow2(LFSR_S0, 8);
    v = MulByPow2(lfsr_s0, 8);
    f = AddM(f, v);
    v = MulByPow2(LFSR_S4, 20);
    v = MulByPow2(lfsr_s4, 20);
    f = AddM(f, v);
    v = MulByPow2(LFSR_S10, 21);
    v = MulByPow2(lfsr_s10, 21);
    f = AddM(f, v);
    v = MulByPow2(LFSR_S13, 17);
    v = MulByPow2(lfsr_s13, 17);
    f = AddM(f, v);
    v = MulByPow2(LFSR_S15, 15);
    v = MulByPow2(lfsr_s15, 15);
    f = AddM(f, v);
    
    /* update the state */
    LFSR_S0 = LFSR_S1;
    LFSR_S1 = LFSR_S2;
    LFSR_S2 = LFSR_S3;
    LFSR_S3 = LFSR_S4;
    LFSR_S4 = LFSR_S5;
    LFSR_S5 = LFSR_S6;
    LFSR_S6 = LFSR_S7;
    LFSR_S7 = LFSR_S8;
    LFSR_S8 = LFSR_S9;
    LFSR_S9 = LFSR_S10;
    LFSR_S10 = LFSR_S11;
    LFSR_S11 = LFSR_S12;
    LFSR_S12 = LFSR_S13;
    LFSR_S13 = LFSR_S14;
    LFSR_S14 = LFSR_S15;
    LFSR_S15 = f;
    lfsr_s0 = lfsr_s1;
    lfsr_s1 = lfsr_s2;
    lfsr_s2 = lfsr_s3;
    lfsr_s3 = lfsr_s4;
    lfsr_s4 = lfsr_s5;
    lfsr_s5 = lfsr_s6;
    lfsr_s6 = lfsr_s7;
    lfsr_s7 = lfsr_s8;
    lfsr_s8 = lfsr_s9;
    lfsr_s9 = lfsr_s10;
    lfsr_s10 = lfsr_s11;
    lfsr_s11 = lfsr_s12;
    lfsr_s12 = lfsr_s13;
    lfsr_s13 = lfsr_s14;
    lfsr_s14 = lfsr_s15;
    lfsr_s15 = f;
  };

  /* BitReorganization */
  inline void BitReorganization(void) {
    BRC_X0 = ((LFSR_S15 & 0x7FFF8000) << 1) | (LFSR_S14 & 0xFFFF);
    BRC_X1 = ((LFSR_S11 & 0xFFFF) << 16) | (LFSR_S9 >> 15);
    BRC_X2 = ((LFSR_S7 & 0xFFFF) << 16) | (LFSR_S5 >> 15);
    BRC_X3 = ((LFSR_S2 & 0xFFFF) << 16) | (LFSR_S0 >> 15);
  /* bit_reorganization */
  inline void bit_reorganization(void) {
    brc_x0 = ((lfsr_s15 & 0x7FFF8000) << 1) | (lfsr_s14 & 0xFFFF);
    brc_x1 = ((lfsr_s11 & 0xFFFF) << 16) | (lfsr_s9 >> 15);
    brc_x2 = ((lfsr_s7 & 0xFFFF) << 16) | (lfsr_s5 >> 15);
    brc_x3 = ((lfsr_s2 & 0xFFFF) << 16) | (lfsr_s0 >> 15);
  };

  #define ROT(a, k) (((a) << k) | ((a) >> (32 - k)))
@@ -287,17 +316,17 @@ private:
  inline uint32_t F(void) {
    uint32_t W, W1, W2, u, v;
    
    W  = (BRC_X0 ^ F_R1) + F_R2;
    W1 = F_R1 + BRC_X1;
    W2 = F_R2 ^ BRC_X2;
    W  = (brc_x0 ^ f_r1) + f_r2;
    W1 = f_r1 + brc_x1;
    W2 = f_r2 ^ brc_x2;
    
    u = L1((W1 << 16) | (W2 >> 16));
    v = L2((W2 << 16) | (W1 >> 16));
    
    F_R1 = MAKEU32(S0[u >> 24], S1[(u >> 16) & 0xFF],
    S0[(u >> 8) & 0xFF], S1[u & 0xFF]);
    F_R2 = MAKEU32(S0[v >> 24], S1[(v >> 16) & 0xFF],
    S0[(v >> 8) & 0xFF], S1[v & 0xFF]);
    f_r1 = MAKEU32(s0[u >> 24], s1[(u >> 16) & 0xFF],
    s0[(u >> 8) & 0xFF], s1[u & 0xFF]);
    f_r2 = MAKEU32(s0[v >> 24], s1[(v >> 16) & 0xFF],
    s0[(v >> 8) & 0xFF], s1[v & 0xFF]);
    
    return W;
  };
@@ -308,90 +337,90 @@ private:
    uint32_t w, nCount;

    /* expand key */
    LFSR_S0 = MAKEU31(k[0], EK_d[0], iv[0]);
    LFSR_S1 = MAKEU31(k[1], EK_d[1], iv[1]);
    LFSR_S2 = MAKEU31(k[2], EK_d[2], iv[2]);
    LFSR_S3 = MAKEU31(k[3], EK_d[3], iv[3]);
    LFSR_S4 = MAKEU31(k[4], EK_d[4], iv[4]);
    LFSR_S5 = MAKEU31(k[5], EK_d[5], iv[5]);
    LFSR_S6 = MAKEU31(k[6], EK_d[6], iv[6]);
    LFSR_S7 = MAKEU31(k[7], EK_d[7], iv[7]);
    LFSR_S8 = MAKEU31(k[8], EK_d[8], iv[8]);
    LFSR_S9 = MAKEU31(k[9], EK_d[9], iv[9]);
    LFSR_S10 = MAKEU31(k[10], EK_d[10], iv[10]);
    LFSR_S11 = MAKEU31(k[11], EK_d[11], iv[11]);
    LFSR_S12 = MAKEU31(k[12], EK_d[12], iv[12]);
    LFSR_S13 = MAKEU31(k[13], EK_d[13], iv[13]);
    LFSR_S14 = MAKEU31(k[14], EK_d[14], iv[14]);
    LFSR_S15 = MAKEU31(k[15], EK_d[15], iv[15]);

    /* set F_R1 and F_R2 to zero */
    F_R1 = 0;
    F_R2 = 0;
    lfsr_s0 = MAKEU31(k[0], EK_d[0], iv[0]);
    lfsr_s1 = MAKEU31(k[1], EK_d[1], iv[1]);
    lfsr_s2 = MAKEU31(k[2], EK_d[2], iv[2]);
    lfsr_s3 = MAKEU31(k[3], EK_d[3], iv[3]);
    lfsr_s4 = MAKEU31(k[4], EK_d[4], iv[4]);
    lfsr_s5 = MAKEU31(k[5], EK_d[5], iv[5]);
    lfsr_s6 = MAKEU31(k[6], EK_d[6], iv[6]);
    lfsr_s7 = MAKEU31(k[7], EK_d[7], iv[7]);
    lfsr_s8 = MAKEU31(k[8], EK_d[8], iv[8]);
    lfsr_s9 = MAKEU31(k[9], EK_d[9], iv[9]);
    lfsr_s10 = MAKEU31(k[10], EK_d[10], iv[10]);
    lfsr_s11 = MAKEU31(k[11], EK_d[11], iv[11]);
    lfsr_s12 = MAKEU31(k[12], EK_d[12], iv[12]);
    lfsr_s13 = MAKEU31(k[13], EK_d[13], iv[13]);
    lfsr_s14 = MAKEU31(k[14], EK_d[14], iv[14]);
    lfsr_s15 = MAKEU31(k[15], EK_d[15], iv[15]);

    /* set f_r1 and f_r2 to zero */
    f_r1 = 0;
    f_r2 = 0;
    nCount = 32;
    while (nCount > 0)
    {
      BitReorganization();
      bit_reorganization();
      w = F();
      LFSRWithInitialisationMode(w >> 1);
      lfsr_with_initialisation_mode(w >> 1);
      nCount --;
    }
  };

  inline void zuc_generate_key_stream(uint32_t* pKeystream, uint32_t KeystreamLen) {
    int i;
    BitReorganization();
    bit_reorganization();
    F(); 			/* discard the output of F */
    LFSRWithWorkMode();
    lfsr_with_work_mode();
    
    for (i = 0; i < KeystreamLen; i ++)
    {
      BitReorganization();
      pKeystream[i] = F() ^ BRC_X3;
      LFSRWithWorkMode();
      bit_reorganization();
      pKeystream[i] = F() ^ brc_x3;
      lfsr_with_work_mode();
    }
  };

  /* The ZUC algorithm, see ref. [3]*/
  inline void ZUC(const uint8_t* k, uint8_t* iv, uint32_t* ks, uint32_t len) {
  inline void zuc(const uint8_t* k, uint8_t* iv, uint32_t* ks, uint32_t len) {
    /* The initialization of ZUC, see page 17 of ref. [3]*/
    zuc_initialize(k, iv);
    /*  The procedure of generating keystream of ZUC, see page 18 of ref. [3]*/
    zuc_generate_key_stream(ks, len);
  };

  inline uint32_t GET_WORD(const uint32_t* DATA, const uint32_t i) {
    uint32_t WORD, ti;
  inline uint32_t get_word(const uint32_t* p_data, const uint32_t i) {
    uint32_t word, ti;
    ti	= i % 32;
    if (ti == 0)
      WORD = DATA[i/32];
      word = p_data[i/32];
    else
      WORD = (DATA[i/32]<<ti) | (DATA[i/32+1]>>(32-ti));
    return WORD;
      word = (p_data[i/32]<<ti) | (p_data[i/32+1]>>(32-ti));
    return word;
  };

  inline uint8_t GET_BIT(const uint8_t* DATA, const uint32_t i) { return (DATA[i/8] & (1<<(7-(i%8)))) ? 1 : 0; };
  inline uint8_t get_bit(const uint8_t* p_data, const uint32_t i) { return (p_data[i/8] & (1<<(7-(i%8)))) ? 1 : 0; };

  /*
  * CK: ciphering key
  * COUNT: frame counter
  * BEARER: radio bearer
  * DIRECTION
  * LENGTH: length of the frame in bits
  * M: original message (input)
  * C: processed message (output)
  * p_knas_enc: ciphering key
  * count: frame counter
  * bearer: radio bearer
  * direction
  * payload_length: length of the frame in bits
  * payload: original message (input)
  * ciphered: processed message (output)
  */
  void zuc_eea3(const uint8_t* CK, const uint32_t COUNT, const uint32_t BEARER, const uint32_t DIRECTION, const uint32_t LENGTH, const uint8_t* M, uint8_t* C);
  void zuc_eea3(const uint8_t* p_knas_enc, const uint32_t count, const uint32_t bearer, const uint32_t direction, const uint32_t payload_length, const uint8_t* payload, uint8_t* ciphered);

  /*
  * IK: integrity key
  * COUNT: frame counter
  * BEARER: radio bearer
  * DIRECTION
  * LENGTH: length of the frame in bits
  * M: original message (input)
  * C: processed message (output)
  * p_knas_int: integrity key
  * count: frame counter
  * bearer: radio bearer
  * direction
  * payload_length: length of the frame in bits
  * payload: original message (input)
  * mac: computed integrity protection (output)
  */
  void zuc_eia3(const uint8_t* IK, const uint32_t COUNT, const uint32_t BEARER, const uint32_t DIRECTION, const uint32_t LENGTH, const uint8_t* M, uint32_t* MAC);
  void zuc_eia3(const uint8_t* p_knas_int, const uint32_t count, const uint32_t bearer, const uint32_t direction, const uint32_t payload_length, const uint8_t* payload, uint32_t* mac);

};
+0 −2
Original line number Diff line number Diff line
@@ -7,6 +7,4 @@ sources := \
    ia3_128.cc                   \


#    zuc.cc

includes := .
+1 −0
Original line number Diff line number Diff line
@@ -155,6 +155,7 @@ system.N2_gNBaMF_P.params := "NGAP/SCTP_FILE/IP_OFFLINE/ETH(mac_src=8c554ac1eee0
#NG_NAS_TestCases.TC_5G_AKA_CRYPTO_FUNCTIONS_TEST_25_01_02
#NG_NAS_TestCases.TC_5G_AKA_CRYPTO_FUNCTIONS_TEST_25_02_01
NG_NAS_TestCases.TC_5G_AKA_CRYPTO_FUNCTIONS_TEST_25_03_01
NG_NAS_TestCases.TC_5G_AKA_CRYPTO_FUNCTIONS_TEST_26_03_01

[GROUPS]
# In this section you can specify groups of hosts. These groups can be used inside the
Loading