Commit 9960fc77 authored by Yann Garcia's avatar Yann Garcia
Browse files

validate cyphering with SNOW 3G & AES; Note: classes to be renamed later

parent 3be1c84f
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -19,10 +19,10 @@
			"path": "../5G_ciphered_NAS_decipher_tool"
		},
		{
			"path": "../../frameworks/CryptoMobile/CryptoMobile"
			"path": "../open5gs"
		},
		{
			"path": "../open5gs"
			"path": "../UERANSIM"
		}
	],
	"settings": {
+182 −64
Original line number Diff line number Diff line
@@ -12,9 +12,12 @@
#include "CommonDefs.hh"

#include "base_time.hh"
//#include "converter.hh"
#include "converter.hh"
#include "loggers.hh"

#include "ia1_128.hh"
#include "ia2_128.hh"
#include "ia3_128.hh"

namespace NG__SecurityDefinitionsAndExternalFunctions {

@@ -28,6 +31,29 @@ namespace NG__SecurityDefinitionsAndExternalFunctions {
//return int2bit(0, 0);
//}
OCTETSTRING fx__NG__NasIntegrityAlgorithm(const OCTETSTRING& p_EncodedNasPdu, const BITSTRING& p_IntegrityAlgorithm, const BITSTRING& p_KNASint, const OCTETSTRING& p_NasCount, const BITSTRING& p_BearerId, const INTEGER& p_Direction){
   loggers::get_instance().log_msg(">>> fx__NG__NasIntegrityAlgorithm: p_EncodedNasPdu: ", p_EncodedNasPdu);
   loggers::get_instance().log_msg(">>> fx__NG__NasIntegrityAlgorithm: p_IntegrityAlgorithm: ", bit2oct(p_IntegrityAlgorithm));
   loggers::get_instance().log_msg(">>> fx__NG__NasIntegrityAlgorithm: p_KNASint: ", bit2oct(p_KNASint));
   loggers::get_instance().log_msg(">>> fx__NG__NasIntegrityAlgorithm: p_NasCount: ", p_NasCount);
   loggers::get_instance().log_msg(">>> fx__NG__NasIntegrityAlgorithm: p_BearerId: ", bit2oct(p_BearerId));
   loggers::get_instance().log_msg(">>> fx__NG__NasIntegrityAlgorithm: p_Direction: ", p_Direction);

   // Sanity checks
   if (p_IntegrityAlgorithm.lengthof() != 4) {
      loggers::get_instance().error("fx__NG__NasCiphering: p_IntegrityAlgorithm: Wrong length");
      return int2oct(0, 0);
   } else if (p_KNASint.lengthof() != 128) {
      loggers::get_instance().error("fx__NG__NasCiphering: p_KNASint: Wrong length");
      return int2oct(0, 0);
   } else if ((p_NasCount.lengthof() != 4) || (p_BearerId.lengthof() != 5)) {
      loggers::get_instance().error("fx__NG__NasCiphering: p_NasCount/p_BearerId: Wrong length");
      return int2oct(0, 0);
   }





   return int2oct(0, 0);
}

@@ -39,9 +65,8 @@ OCTETSTRING fx__NG__NasCiphering(const OCTETSTRING& p_EncodedNasPdu,const BITST
   loggers::get_instance().log_msg(">>> fx__NG__NasCiphering: p_BearerId: ", bit2oct(p_BearerId));
   loggers::get_instance().log_msg(">>> fx__NG__NasCiphering: p_Direction: ", p_Direction);

   // sanity checks
   if (p_CipheringAlgorithm.lengthof() != 4)/* || (p_CipheringAlgorithm.get_value() != 0b0001)*/ {
      /// 0b0001 = EEA2 (AES-128)
   // Sanity checks
   if (p_CipheringAlgorithm.lengthof() != 4) {
      loggers::get_instance().error("fx__NG__NasCiphering: p_CipheringAlgorithm: Wrong length");
      return int2oct(0, 0);
   } else if (p_KNASenc.lengthof() != 128) {
@@ -52,74 +77,167 @@ OCTETSTRING fx__NG__NasCiphering(const OCTETSTRING& p_EncodedNasPdu,const BITST
      return int2oct(0, 0);
   }

   // Cypher key
   const unsigned char* key = (const unsigned char*)bit2oct(p_KNASenc);

   // Construct IV (counter block) as per 3GPP TS 33.501 Annex C.3
   const unsigned char iv_length = 16;
   unsigned char iv[iv_length] = {0};
   const unsigned char* nas_count = (const unsigned char*)p_NasCount;
   iv[0] = nas_count[0];
   iv[1] = nas_count[1];
   iv[2] = nas_count[2];
   iv[3] = nas_count[3];
   // BearerId: 5 bits, Direction: 1 bit (LSB)
   unsigned char bearer_dir = ((*((const unsigned char*)bit2oct(p_BearerId)) & 0x1F) << 3) | (((unsigned char)p_Direction.get_long_long_val() & 0x01) << 2);
   loggers::get_instance().log("fx__NG__NasCiphering: bearer_dir=0x%02x", bearer_dir);
   iv[4] = bearer_dir;
   unsigned int u = p_EncodedNasPdu.lengthof();
   loggers::get_instance().log_to_hexa("fx__NG__NasCiphering: p_EncodedNasPdu.lengthof()=", (unsigned char*)&u, 4);
   loggers::get_instance().log("fx__NG__NasCiphering: >> 8 %02x=", u >> 8);
   loggers::get_instance().log("fx__NG__NasCiphering: >> 16 %02x=", u >> 16);
   loggers::get_instance().log("fx__NG__NasCiphering: >> 24 %02x=", u >> 24);
   loggers::get_instance().log("fx__NG__NasCiphering: << 8 %02x=", u << 8);
   OCTETSTRING data_len = int2oct(p_EncodedNasPdu.lengthof(), 4);
   const unsigned char* data_len_ = (const unsigned char*)data_len;
   iv[5] = data_len_[0];
   iv[6] = data_len_[1];
   iv[7] = data_len_[2];
   iv[8] = data_len_[3];
   // Remaining bytes are zero (already set)
   loggers::get_instance().log_to_hexa("fx__NG__NasCiphering: iv=", iv, iv_length);

   // Prepare input/output
   const unsigned char* plaintext = (const unsigned char*)p_EncodedNasPdu;
   int plaintext_len = p_EncodedNasPdu.lengthof();
   std::vector<unsigned char> ciphertext(plaintext_len);
   loggers::get_instance().log_to_hexa("fx__NG__NasCiphering: plaintext=", plaintext, plaintext_len);

   // OpenSSL AES-CTR encryption
   EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
   int outlen1 = 0, outlen2 = 0;
   if (!ctx) {
      loggers::get_instance().error("fx__NG__NasCiphering: EVP_CIPHER_CTX_new failed");
      return int2oct(0, 0);
   unsigned char *cyphered;
   uint32_t cyphered_length;
   uint32_t nas_count = converter::get_instance().bytes_to_int(std::vector<uint8_t>(static_cast<const unsigned char*>(p_NasCount), static_cast<const unsigned char*>(p_NasCount) + p_NasCount.lengthof()));
   int result = -1;
   if (bit2int(p_CipheringAlgorithm) == 0) { // IA0/NEA0: No cyphering
      loggers::get_instance().log("fx__NG__NasCiphering: No cyphering");
      return p_EncodedNasPdu; // no cyphering
   } else if (bit2int(p_CipheringAlgorithm) == 1) { // IA1_128/NEA1_128: Snow 3G based algorithm
      loggers::get_instance().log("fx__NG__NasCiphering: ia1_128 selected");
      ia1_128 enc;
      result = enc.encrypt(
                           bit2int(p_CipheringAlgorithm), 
                           static_cast<const unsigned char*>(bit2oct(p_KNASenc)), 
                           nas_count, 
                           bit2int(p_BearerId), 
                           p_Direction, 
                           static_cast<const unsigned char*>(p_EncodedNasPdu), 
                           p_EncodedNasPdu.lengthof(),
                           &cyphered,
                           &cyphered_length
                           );
   } else if (bit2int(p_CipheringAlgorithm) == 2) { // IA2_128/NEA2_128: AES 128 CTR based algorithm
      loggers::get_instance().log("fx__NG__NasCiphering: ia2_128 selected");
      ia2_128 enc;
      result = enc.encrypt(
                           bit2int(p_CipheringAlgorithm), 
                           static_cast<const unsigned char*>(bit2oct(p_KNASenc)), 
                           nas_count, 
                           bit2int(p_BearerId), 
                           p_Direction, 
                           static_cast<const unsigned char*>(p_EncodedNasPdu), 
                           p_EncodedNasPdu.lengthof(),
                           &cyphered,
                           &cyphered_length
                           );
   } else if (bit2int(p_CipheringAlgorithm) == 3) { // IA3_128/NEA3_128: ZUC based algorithm
      loggers::get_instance().log("fx__NG__NasCiphering: ia3_128 selected");
      ia3_128 enc;
      result = enc.encrypt(
                           bit2int(p_CipheringAlgorithm), 
                           static_cast<const unsigned char*>(bit2oct(p_KNASenc)), 
                           nas_count, 
                           bit2int(p_BearerId), 
                           p_Direction, 
                           static_cast<const unsigned char*>(p_EncodedNasPdu), 
                           p_EncodedNasPdu.lengthof(),
                           &cyphered,
                           &cyphered_length
                           );
   } else if (bit2int(p_CipheringAlgorithm) == 4) { // IA4
      loggers::get_instance().error("fx__NG__NasCiphering: p_CipheringAlgorithm: Unsupported algorithm");
   } else if (bit2int(p_CipheringAlgorithm) == 5) { // IA5
      loggers::get_instance().error("fx__NG__NasCiphering: p_CipheringAlgorithm: Unsupported algorithm");
   } else if (bit2int(p_CipheringAlgorithm) == 6) { // IA6
      loggers::get_instance().error("fx__NG__NasCiphering: p_CipheringAlgorithm: Unsupported algorithm");
   } else if (bit2int(p_CipheringAlgorithm) == 7) { // IA7
      loggers::get_instance().error("fx__NG__NasCiphering: p_CipheringAlgorithm: Unsupported algorithm");
   } else {
      loggers::get_instance().error("fx__NG__NasCiphering: p_CipheringAlgorithm: Unknown algorithm");
   }
   if (EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), NULL, key, iv) != 1) {
      loggers::get_instance().error("fx__NG__NasCiphering: EVP_EncryptInit_ex failed");
      EVP_CIPHER_CTX_free(ctx);
   if (result != 0) {
      loggers::get_instance().error("fx__NG__NasCiphering: ia2_128.encrypt() failed");
      return int2oct(0, 0);
   }
   if (EVP_EncryptUpdate(ctx, ciphertext.data(), &outlen1, plaintext, plaintext_len) != 1) {
      loggers::get_instance().error("fx__NG__NasCiphering: EVP_EncryptUpdate failed");
      EVP_CIPHER_CTX_free(ctx);
      return int2oct(0, 0);
   OCTETSTRING os(cyphered_length, (const unsigned char*)cyphered);
   free(cyphered);

   loggers::get_instance().log_msg("<<< fx__NG__NasCiphering: ", os);
   return os;
}
   if (EVP_EncryptFinal_ex(ctx, ciphertext.data() + outlen1, &outlen2) != 1) {
      loggers::get_instance().error("fx__NG__NasCiphering: EVP_EncryptFinal_ex failed");
      EVP_CIPHER_CTX_free(ctx);

OCTETSTRING fx__NG__NasDeciphering(const OCTETSTRING& p_CipheredNasMsg, const BITSTRING& p_CipheringAlgorithm, const BITSTRING& p_KNASenc, const OCTETSTRING& p_NasCount, const BITSTRING& p_BearerId, const INTEGER& p_Direction){
   loggers::get_instance().log_msg(">>> fx__NG__NasDeciphering: p_CipheredNasMsg: ", p_CipheredNasMsg);
   loggers::get_instance().log_msg(">>> fx__NG__NasDeciphering: p_CipheringAlgorithm: ", bit2oct(p_CipheringAlgorithm));
   loggers::get_instance().log_msg(">>> fx__NG__NasDeciphering: p_KNASenc: ", bit2oct(p_KNASenc));
   loggers::get_instance().log_msg(">>> fx__NG__NasDeciphering: p_NasCount: ", p_NasCount);
   loggers::get_instance().log_msg(">>> fx__NG__NasDeciphering: p_BearerId: ", bit2oct(p_BearerId));
   loggers::get_instance().log_msg(">>> fx__NG__NasDeciphering: p_Direction: ", p_Direction);

   // Sanity checks
   if (p_CipheringAlgorithm.lengthof() != 4) {
      loggers::get_instance().error("fx__NG__NasDeciphering: p_CipheringAlgorithm: Wrong length");
      return int2oct(0, 0);
   } else if (p_KNASenc.lengthof() != 128) {
      loggers::get_instance().error("fx__NG__NasDeciphering: p_KNASenc: Wrong length");
      return int2oct(0, 0);
   } else if ((p_NasCount.lengthof() != 4) || (p_BearerId.lengthof() != 5)) {
      loggers::get_instance().error("fx__NG__NasDeciphering: p_NasCount/p_BearerId: Wrong length");
      return int2oct(0, 0);
   }
   EVP_CIPHER_CTX_free(ctx);

   OCTETSTRING result = OCTETSTRING(outlen1 + outlen2, (const unsigned char*)ciphertext.data());
   loggers::get_instance().log_msg("<<< fx__NG__NasCiphering: result: ", result);
   return result;
   unsigned char *payload;
   uint32_t payload_length;
   uint32_t nas_count = converter::get_instance().bytes_to_int(std::vector<uint8_t>(static_cast<const unsigned char*>(p_NasCount), static_cast<const unsigned char*>(p_NasCount) + p_NasCount.lengthof()));
   int result = -1;
   if (bit2int(p_CipheringAlgorithm) == 0) { // IA0/NEA0: No cyphering
      loggers::get_instance().log("fx__NG__NasDeciphering: No cyphering");
      return p_CipheredNasMsg; // no cyphering
   } else if (bit2int(p_CipheringAlgorithm) == 1) { // IA1_128/NEA1_128: Snow 3G based algorithm
      loggers::get_instance().log("fx__NG__NasDeciphering: ia1_128 selected");
      ia1_128 enc;
      result = enc.decrypt(
                           bit2int(p_CipheringAlgorithm), 
                           static_cast<const unsigned char*>(bit2oct(p_KNASenc)), 
                           nas_count, 
                           bit2int(p_BearerId), 
                           p_Direction, 
                           static_cast<const unsigned char*>(p_CipheredNasMsg), 
                           p_CipheredNasMsg.lengthof(),
                           &payload,
                           &payload_length
                           );
   } else if (bit2int(p_CipheringAlgorithm) == 2) { // IA2_128/NEA2_128: AES 128 CTR based algorithm
      loggers::get_instance().log("fx__NG__NasDeciphering: ia2_128 selected");
      ia2_128 enc;
      result = enc.decrypt(
                           bit2int(p_CipheringAlgorithm), 
                           static_cast<const unsigned char*>(bit2oct(p_KNASenc)), 
                           nas_count, 
                           bit2int(p_BearerId), 
                           p_Direction, 
                           static_cast<const unsigned char*>(p_CipheredNasMsg), 
                           p_CipheredNasMsg.lengthof(),
                           &payload,
                           &payload_length
                           );
   } else if (bit2int(p_CipheringAlgorithm) == 3) { // IA3_128/NEA3_128: ZUC based algorithm
      loggers::get_instance().log("fx__NG__NasDeciphering: ia1_128 selected");
      ia3_128 enc;
      result = enc.decrypt(
                           bit2int(p_CipheringAlgorithm), 
                           static_cast<const unsigned char*>(bit2oct(p_KNASenc)), 
                           nas_count, 
                           bit2int(p_BearerId), 
                           p_Direction, 
                           static_cast<const unsigned char*>(p_CipheredNasMsg), 
                           p_CipheredNasMsg.lengthof(),
                           &payload,
                           &payload_length
                           );
   } else if (bit2int(p_CipheringAlgorithm) == 4) { // IA4
      loggers::get_instance().error("fx__NG__NasDeciphering: p_CipheringAlgorithm: Unsupported algorithm");
   } else if (bit2int(p_CipheringAlgorithm) == 5) { // IA5
      loggers::get_instance().error("fx__NG__NasDeciphering: p_CipheringAlgorithm: Unsupported algorithm");
   } else if (bit2int(p_CipheringAlgorithm) == 6) { // IA6
      loggers::get_instance().error("fx__NG__NasDeciphering: p_CipheringAlgorithm: Unsupported algorithm");
   } else if (bit2int(p_CipheringAlgorithm) == 7) { // IA7
      loggers::get_instance().error("fx__NG__NasDeciphering: p_CipheringAlgorithm: Unsupported algorithm");
   } else {
      loggers::get_instance().error("fx__NG__NasDeciphering: p_CipheringAlgorithm: Unknown algorithm");
   }

OCTETSTRING fx__NG__NasDeciphering(const OCTETSTRING& p_CipheredNasMsg, const BITSTRING& p_CipheringAlgorithm, const BITSTRING& p_KNASenc, const OCTETSTRING& p_NasCount, const BITSTRING& p_BearerId, const INTEGER& p_Direction){
   if (result != 0) {
      loggers::get_instance().error("fx__NG__NasDeciphering: decrypt() failed");
      return int2oct(0, 0);
   }
   OCTETSTRING os(payload_length, (const unsigned char*)payload);
   free(payload);

   loggers::get_instance().log_msg("<<< fx__NG__NasDeciphering: ", os);
   return os;
}



+1 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ namespace CommonDefs {

      return;
   }

   //void fx__CalculateFCS32(BITSTRING const&)   {
   BITSTRING fx__CalculateFCS32(const BITSTRING& p__TMSI){
      loggers::get_instance().log_msg(">>> fx__CalculateFCS32: p__TMSI: ", p__TMSI);
+164 −0
Original line number Diff line number Diff line
/**
 * @file ia1_128.cpp
 * @brief 3GPP SNOW 3G-based Encryption class implementation
 * @author Generated for 3GPP NAS encryption
 * @date 2024
 * 
 * This implementation uses the SNOW 3G algorithm as specified in
 * 3GPP TS 33.401. For the actual SNOW 3G cipher implementation,
 * this code can be linked with libraries such as libmilenage or
 * open5gs crypto library.
 */

#include "ia1_128.hh"

//#include "snow3g.hh"

#include "loggers.hh"

namespace {
  constexpr size_t KEY_SIZE = 16;  // 128 bits = 16 bytes
  constexpr size_t IV_SIZE = 16;   // Initialization vector size
}

int ia1_128::encrypt(const uint8_t algo_id,
                     const unsigned char* knas_enc,
                     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) {
  loggers::get_instance().log_to_hexa(">>> ia1_128::encrypt: knas_enc", knas_enc, KEY_SIZE);
  loggers::get_instance().log_to_hexa(">>> ia1_128::encrypt: payload", payload, payload_length);
  loggers::get_instance().log(">>> ia1_128::encrypt: algo_id: %d", algo_id);
  loggers::get_instance().log(">>> ia1_128::encrypt: count: %u", count);
  loggers::get_instance().log(">>> ia1_128::encrypt: bearer: %d", bearer);
  loggers::get_instance().log(">>> ia1_128::encrypt: direction: %d", direction);

  // Input validation
  if (!knas_enc || !payload || !cyphered || !cyphered_length) {
    loggers::get_instance().error("ia1_128::encrypt: Wrong input parameters");
    return -1;
  }

  if (payload_length == 0) {
    loggers::get_instance().error("ia1_128::encrypt: Wrong payload length");
    *cyphered = nullptr;
    *cyphered_length = 0;
    return 0;
  }

  // Allocate memory for ciphertext
  *cyphered = static_cast<unsigned char*>(std::malloc(payload_length));
  if (!*cyphered) {
    loggers::get_instance().error("ia1_128::encrypt: Failed to allocate memory");
    return -1;
  }
  snow3g_context_t ctx;
  snow3g_initialize(count, bearer, direction, (const char *)knas_enc, &ctx);
  snow3g_generate(payload_length, payload, *cyphered, &ctx);
  *cyphered_length = payload_length;
  loggers::get_instance().log("ia1_128::encrypt: cyphered_length: %d", *cyphered_length);
  loggers::get_instance().log_to_hexa("ia1_128::encrypt: cyphered: ", *cyphered, *cyphered_length);

  loggers::get_instance().log("<<< ia1_128::encrypt: ret: 0");
  return 0;
}

int ia1_128::decrypt(const uint8_t algo_id,
                     const unsigned char* knas_enc,
                     const uint32_t count,
                     const uint8_t bearer,
                     const uint8_t direction,
                     const unsigned char* cyphered,
                     const uint32_t cyphered_length,
                     unsigned char** payload,
                     uint32_t* payload_length) {
  loggers::get_instance().log(">>> ia1_128::decrypt: Starting decryption");
  loggers::get_instance().log_to_hexa(">>> ia1_128::decrypt: knas_enc", knas_enc, KEY_SIZE);
  loggers::get_instance().log_to_hexa(">>> ia1_128::decrypt: cyphered", cyphered, cyphered_length);
  loggers::get_instance().log(">>> ia1_128::decrypt: algo_id: %d", algo_id);
  loggers::get_instance().log(">>> ia1_128::decrypt: count: %u", count);
  loggers::get_instance().log(">>> ia1_128::decrypt: bearer: %d", bearer);
  loggers::get_instance().log(">>> ia1_128::decrypt: direction: %d", direction);

  return encrypt(algo_id, knas_enc, count, bearer, direction, 
                 cyphered, cyphered_length, payload, payload_length);
}

int ia1_128::snow3g_initialize(uint32_t count, uint8_t bearer, uint8_t direction, const char *knas_enc, snow3g_context_t *ctx) {
  loggers::get_instance().log_to_hexa(">>> ia1_128::snow3g_initialize: knas_enc", (const unsigned char*)knas_enc, 16);
  loggers::get_instance().log(">>> ia1_128::snow3g_initialize: count: %u", count);
  loggers::get_instance().log(">>> ia1_128::snow3g_initialize: bearer: %d", bearer);
  loggers::get_instance().log(">>> ia1_128::snow3g_initialize: direction: %d", direction);

  // Sanity checks
  if (ctx == NULL) {
    loggers::get_instance().error("ia1_128::snow3g_initialize: Wrong parameters");
    return -1;
  }

  struct snow_key_st snow_key;
  memset(&snow_key, 0, sizeof(snow_key));
  snow_key.key[3] = WORD_128(knas_enc, 0);
  snow_key.key[2] = WORD_128(knas_enc, 1);
  snow_key.key[1] = WORD_128(knas_enc, 2);
  snow_key.key[0] = WORD_128(knas_enc, 3);

  snow_key.iv[3] = count;
  snow_key.iv[2] = ((bearer & 0x1F) << 27) | ((direction & 0x01) << 26);
  snow_key.iv[1] = snow_key.iv[3];
  snow_key.iv[0] = snow_key.iv[2];

  loggers::get_instance().log_to_hexa("ia1_128::snow3g_initialize: snow_key.key", (const unsigned char*)snow_key.key, 4 * sizeof(uint32_t));
  loggers::get_instance().log_to_hexa("ia1_128::snow3g_initialize: snow_key.iv", (const unsigned char*)snow_key.iv, 4 * sizeof(uint32_t));

  snow_set_key(snow_key, ctx);

  return 0;
}

int ia1_128::snow3g_generate(size_t nb_byte, const unsigned char *in, unsigned char *out, snow3g_context_t *ctx) {
  loggers::get_instance().log(">>> SNOW: nb_byte: %u", nb_byte);
  loggers::get_instance().log_to_hexa(">>> SNOW: in", (const unsigned char*)in, nb_byte);

  // Sanity checks
  if (ctx == NULL) {
    loggers::get_instance().error("SNOW: Wrong parameters");
    return -1;
  }

  size_t i = 0;
  size_t nb_word = nb_byte/4;
  size_t r = nb_byte % 4;
  uint32_t *in_word = (uint32_t*) in;
  uint32_t *out_word = (uint32_t*) out;

  /* init */
  clock_fsm(ctx);
  lfsr_keystream(ctx);

  for (i = 0; i < nb_word; i++) {
    uint32_t f;
    f = clock_fsm(ctx) ^ ctx->lfsr[0];
    out_word[i] = in_word[i] ^ be32toh(f);
    lfsr_keystream(ctx);
  }

  if (r) {
    uint32_t f;
    uint32_t last_out = 0;
    uint32_t last_in = 0;

    f = clock_fsm(ctx) ^ ctx->lfsr[0];
    memcpy(&last_in, in + nb_word*4, r);
    last_out = last_in ^ be32toh(f);
    memcpy(out + nb_word*4, &last_out, r);
    lfsr_keystream(ctx);
  }

  loggers::get_instance().log_to_hexa("<<< SNOW: out", (const unsigned char*)out, nb_byte);
  return 0;
}
+966 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading