From 73ae18dabb1114fa25162ef664daf1d75554dcb3 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Sun, 28 Apr 2024 16:59:48 +0200 Subject: [PATCH 1/5] nr pdcp: add support for nea1 --- CMakeLists.txt | 1 + openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c | 20 ++++-- .../LAYER2/nr_pdcp/nr_pdcp_security_nea1.c | 69 +++++++++++++++++++ .../LAYER2/nr_pdcp/nr_pdcp_security_nea1.h | 38 ++++++++++ 4 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.c create mode 100644 openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b78b50e5f1..627b87593d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1206,6 +1206,7 @@ set(NR_PDCP_SRC ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_sdu.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_timer_thread.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea2.c + ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_security_nea1.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia2.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/nr_pdcp_integrity_nia1.c ${OPENAIR2_DIR}/LAYER2/nr_pdcp/asn1_utils.c diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c index c125eb41f2..f3402bcf81 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_entity.c @@ -26,6 +26,7 @@ #include #include "nr_pdcp_security_nea2.h" +#include "nr_pdcp_security_nea1.h" #include "nr_pdcp_integrity_nia2.h" #include "nr_pdcp_integrity_nia1.h" #include "nr_pdcp_sdu.h" @@ -373,16 +374,21 @@ static void nr_pdcp_entity_set_security(struct nr_pdcp_entity_t *entity, } if (parameters->ciphering_algorithm != 0 && parameters->ciphering_algorithm != -1) { - if (parameters->ciphering_algorithm != 2) { - LOG_E(PDCP, "FATAL: only nea2 supported for the moment\n"); - exit(1); - } entity->has_ciphering = 1; if (entity->free_security != NULL) entity->free_security(entity->security_context); - entity->security_context = nr_pdcp_security_nea2_init(entity->security_keys_and_algos.ciphering_key); - entity->cipher = nr_pdcp_security_nea2_cipher; - entity->free_security = nr_pdcp_security_nea2_free_security; + if (parameters->ciphering_algorithm == 2) { + entity->security_context = nr_pdcp_security_nea2_init(entity->security_keys_and_algos.ciphering_key); + entity->cipher = nr_pdcp_security_nea2_cipher; + entity->free_security = nr_pdcp_security_nea2_free_security; + } else if (parameters->ciphering_algorithm == 1) { + entity->security_context = nr_pdcp_security_nea1_init(entity->security_keys_and_algos.ciphering_key); + entity->cipher = nr_pdcp_security_nea1_cipher; + entity->free_security = nr_pdcp_security_nea1_free_security; + } else { + LOG_E(PDCP, "FATAL: only nea1 and nea2 supported for the moment\n"); + exit(1); + } } } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.c new file mode 100644 index 0000000000..1cb29b3a81 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.c @@ -0,0 +1,69 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr_pdcp_security_nea1.h" + +#include +#include + +#include "assertions.h" + +stream_security_context_t *nr_pdcp_security_nea1_init(unsigned char *ciphering_key) +{ + nas_stream_cipher_t *ret; + + ret = calloc(1, sizeof(*ret)); + AssertFatal(ret != NULL, "out of memory\n"); + ret->context = malloc(16); + AssertFatal(ret->context != NULL, "out of memory\n"); + memcpy(ret->context, ciphering_key, 16); + + return (stream_security_context_t *)ret; +} + +void nr_pdcp_security_nea1_cipher(stream_security_context_t *security_context, + unsigned char *buffer, + int length, + int bearer, + int count, + int direction) +{ + nas_stream_cipher_t *ctx = (nas_stream_cipher_t *)security_context; + + ctx->message = buffer; + ctx->count = count; + ctx->bearer = bearer - 1; + ctx->direction = direction; + ctx->blength = length * 8; + + uint8_t out[length]; + + stream_compute_encrypt(EEA1_128_ALG_ID, ctx, out); + + memcpy(buffer, out, length); +} + +void nr_pdcp_security_nea1_free_security(stream_security_context_t *security_context) +{ + nas_stream_cipher_t *ctx = (nas_stream_cipher_t *)security_context; + free(ctx->context); + free(ctx); +} diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.h b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.h new file mode 100644 index 0000000000..1338739298 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_security_nea1.h @@ -0,0 +1,38 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _NR_PDCP_SECURITY_NEA1_H_ +#define _NR_PDCP_SECURITY_NEA1_H_ + +#include "openair3/SECU/secu_defs.h" + +stream_security_context_t *nr_pdcp_security_nea1_init(unsigned char *ciphering_key); + +void nr_pdcp_security_nea1_cipher(stream_security_context_t *security_context, + unsigned char *buffer, + int length, + int bearer, + int count, + int direction); + +void nr_pdcp_security_nea1_free_security(stream_security_context_t *security_context); + +#endif /* _NR_PDCP_SECURITY_NEA1_H_ */ From 18f7a702a4c0a712d1d800956e2d4c1d02709cc4 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Tue, 11 Jun 2024 21:52:02 +0200 Subject: [PATCH 2/5] snow3g: provide a faster implementation --- openair3/SECU/nas_stream_eea1.c | 78 +-- openair3/SECU/nas_stream_eea1.h | 3 - openair3/SECU/nas_stream_eia1.c | 193 +----- openair3/SECU/snow3g.c | 1069 +++++++++++++++++++++++-------- openair3/SECU/snow3g.h | 71 +- 5 files changed, 830 insertions(+), 584 deletions(-) diff --git a/openair3/SECU/nas_stream_eea1.c b/openair3/SECU/nas_stream_eea1.c index 027205353b..0a8f60a010 100644 --- a/openair3/SECU/nas_stream_eea1.c +++ b/openair3/SECU/nas_stream_eea1.c @@ -20,86 +20,22 @@ */ #include -#include -#include #include #include "assertions.h" -#include "conversions.h" #include "nas_stream_eea1.h" #include "snow3g.h" void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t *out) { - snow_3g_context_t snow_3g_context; - int n ; - int i = 0; - uint32_t zero_bit = 0; - //uint32_t byte_length; - uint32_t *KS; - uint32_t K[4],IV[4]; uint8_t *key = (uint8_t *)stream_cipher->context; - - DevAssert(stream_cipher != NULL); - DevAssert(out != NULL); - - n = ( stream_cipher->blength + 31 ) / 32; - zero_bit = stream_cipher->blength & 0x7; - //byte_length = stream_cipher->blength >> 3; - - memset(&snow_3g_context, 0, sizeof(snow_3g_context)); - /*Initialisation*/ - /* Load the confidentiality key for SNOW 3G initialization as in section 3.4. */ - memcpy(K+3,key+0,4); /*K[3] = key[0]; we assume - K[3]=key[0]||key[1]||...||key[31] , with key[0] the - * most important bit of key*/ - memcpy(K+2,key+4,4); /*K[2] = key[1];*/ - memcpy(K+1,key+8,4); /*K[1] = key[2];*/ - memcpy(K+0,key+12,4); /*K[0] = key[3]; we assume - * K[0]=key[96]||key[97]||...||key[127] , with key[127] the - * least important bit of key*/ - K[3] = hton_int32(K[3]); - K[2] = hton_int32(K[2]); - K[1] = hton_int32(K[1]); - K[0] = hton_int32(K[0]); - /* Prepare the initialization vector (IV) for SNOW 3G initialization as in section 3.4. */ - IV[3] = stream_cipher->count; - IV[2] = ((((uint32_t)stream_cipher->bearer) << 3) | ((((uint32_t)stream_cipher->direction) & 0x1) << 2)) << 24; - IV[1] = IV[3]; - IV[0] = IV[2]; - - /* Run SNOW 3G algorithm to generate sequence of key stream bits KS*/ - snow3g_initialize(K, IV, &snow_3g_context); - KS = (uint32_t *)malloc(4*n); - snow3g_generate_key_stream(n,(uint32_t*)KS, &snow_3g_context); - - if (zero_bit > 0) { - KS[n - 1] = KS[n - 1] & (uint32_t)(0xFFFFFFFF << (8 - zero_bit)); - } - - for (i=0; imessage[i] ^= *(((uint8_t*)KS)+i); - } - - int ceil_index = 0; - - if (zero_bit > 0) { - ceil_index = (stream_cipher->blength+7) >> 3; - stream_cipher->message[ceil_index - 1] = stream_cipher->message[ceil_index - 1] & (uint8_t)(0xFF << (8 - zero_bit)); - } - - free(KS); - memcpy(out, stream_cipher->message, n*4); - - if (zero_bit > 0) { - out[ceil_index - 1] = stream_cipher->message[ceil_index - 1]; - } + snow3g_ciphering(stream_cipher->count, + stream_cipher->bearer, + stream_cipher->direction, + key, + stream_cipher->blength / 8, + stream_cipher->message, + out); } stream_security_context_t *stream_ciphering_init_eea1(const uint8_t *ciphering_key) diff --git a/openair3/SECU/nas_stream_eea1.h b/openair3/SECU/nas_stream_eea1.h index ebddd7af35..200c2a2449 100644 --- a/openair3/SECU/nas_stream_eea1.h +++ b/openair3/SECU/nas_stream_eea1.h @@ -24,9 +24,6 @@ #include "secu_defs.h" -#include -#include - void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t *out); stream_security_context_t *stream_ciphering_init_eea1(const uint8_t *ciphering_key); diff --git a/openair3/SECU/nas_stream_eia1.c b/openair3/SECU/nas_stream_eia1.c index dd514c777b..8030b7e894 100644 --- a/openair3/SECU/nas_stream_eia1.c +++ b/openair3/SECU/nas_stream_eia1.c @@ -19,105 +19,12 @@ * contact@openairinterface.org */ -#include -#include -#include #include -#include // double ceil(double x); #include "nas_stream_eia1.h" - #include "assertions.h" -#include "conversions.h" #include "snow3g.h" -#define SECU_DEBUG - -// see spec 3GPP Confidentiality and Integrity Algorithms UEA2&UIA2. Document 1: UEA2 and UIA2 Specification. Version 1.1 - -/* MUL64x. - * Input V: a 64-bit input. - * Input c: a 64-bit input. - * Output : a 64-bit output. - * A 64-bit memory is allocated which is to be freed by the calling - * function. - * See section 4.3.2 for details. - */ -static uint64_t MUL64x(uint64_t V, uint64_t c) -{ - if ( V & 0x8000000000000000 ) - return (V << 1) ^ c; - else - return V << 1; -} -/* MUL64xPOW. - * Input V: a 64-bit input. - * Input i: a positive integer. - * Input c: a 64-bit input. - * Output : a 64-bit output. - * A 64-bit memory is allocated which is to be freed by the calling -function. - * See section 4.3.3 for details. - */ -static uint64_t MUL64xPOW(uint64_t V, uint32_t i, uint64_t c) -{ - if ( i == 0) - return V; - else - return MUL64x( MUL64xPOW(V,i-1,c) , c); -} -/* MUL64. - * Input V: a 64-bit input. - * Input P: a 64-bit input. - * Input c: a 64-bit input. - * Output : a 64-bit output. - * A 64-bit memory is allocated which is to be freed by the calling - * function. - * See section 4.3.4 for details. - */ -static uint64_t MUL64(uint64_t V, uint64_t P, uint64_t c) -{ - uint64_t result = 0; - int i = 0; - - for ( i=0; i<64; i++) { - if( ( P>>i ) & 0x1 ) - result ^= MUL64xPOW(V,i,c); - } - - return result; -} - -/* read a big endian uint64_t at given address (potentially not 64-bits aligned) - * don't read more than 'available_bytes' - * (use 0 if no byte to read) - * (note: the compiler will optimize this, no need to do better) - */ -static inline uint64_t U64(uint8_t *p, int available_bytes) -{ - uint64_t a = 0; - uint64_t b = 0; - uint64_t c = 0; - uint64_t d = 0; - uint64_t e = 0; - uint64_t f = 0; - uint64_t g = 0; - uint64_t h = 0; - switch (available_bytes) { - case 8: h = p[7]; /* falltrough */ - case 7: g = p[6]; /* falltrough */ - case 6: f = p[5]; /* falltrough */ - case 5: e = p[4]; /* falltrough */ - case 4: d = p[3]; /* falltrough */ - case 3: c = p[2]; /* falltrough */ - case 2: b = p[1]; /* falltrough */ - case 1: a = p[0]; - } - - return (a << (32+24)) | (b << (32+16)) | (c << (32+8)) | (d << 32) - | (e << 24) | (f << 16) | (g << 8) | h; -} - /*! * @brief Create integrity cmac t for a given message. * @param[in] stream_cipher Structure containing various variables to setup encoding @@ -125,98 +32,14 @@ static inline uint64_t U64(uint8_t *p, int available_bytes) */ void nas_stream_encrypt_eia1(nas_stream_cipher_t const *stream_cipher, uint8_t out[4]) { - snow_3g_context_t snow_3g_context; - uint32_t K[4],IV[4], z[5]; - int i=0,D; - uint32_t MAC_I = 0; - uint64_t EVAL; - uint64_t V; - uint64_t P; - uint64_t Q; - uint64_t c; - uint64_t M_D_2; - int rem_bits; - uint8_t *key = (uint8_t *)stream_cipher->context; - - /* Load the Integrity Key for SNOW3G initialization as in section 4.4. */ - memcpy(K+3,key+0,4); /*K[3] = key[0]; we assume - K[3]=key[0]||key[1]||...||key[31] , with key[0] the - * most important bit of key*/ - memcpy(K+2,key+4,4); /*K[2] = key[1];*/ - memcpy(K+1,key+8,4); /*K[1] = key[2];*/ - memcpy(K+0,key+12,4); /*K[0] = key[3]; we assume - K[0]=key[96]||key[97]||...||key[127] , with key[127] the - * least important bit of key*/ - K[3] = hton_int32(K[3]); - K[2] = hton_int32(K[2]); - K[1] = hton_int32(K[1]); - K[0] = hton_int32(K[0]); - /* Prepare the Initialization Vector (IV) for SNOW3G initialization as in - section 4.4. */ - IV[3] = (uint32_t)stream_cipher->count; - IV[2] = ((((uint32_t)stream_cipher->bearer) & 0x0000001F) << 27); - IV[1] = (uint32_t)(stream_cipher->count) ^ ( (uint32_t)(stream_cipher->direction) << 31 ) ; - IV[0] = ((((uint32_t)stream_cipher->bearer) & 0x0000001F) << 27) ^ ((uint32_t)(stream_cipher->direction & 0x00000001) << 15); - //printf ("K:\n"); - //hexprint(K, 16); - //printf ("K[0]:%08X\n",K[0]); - //printf ("K[1]:%08X\n",K[1]); - //printf ("K[2]:%08X\n",K[2]); - //printf ("K[3]:%08X\n",K[3]); - - //printf ("IV:\n"); - //hexprint(IV, 16); - //printf ("IV[0]:%08X\n",IV[0]); - //printf ("IV[1]:%08X\n",IV[1]); - //printf ("IV[2]:%08X\n",IV[2]); - //printf ("IV[3]:%08X\n",IV[3]); - z[0] = z[1] = z[2] = z[3] = z[4] = 0; - /* Run SNOW 3G to produce 5 keystream words z_1, z_2, z_3, z_4 and z_5. */ - snow3g_initialize(K, IV, &snow_3g_context); - snow3g_generate_key_stream(5, z, &snow_3g_context); - //printf ("z[0]:%08X\n",z[0]); - //printf ("z[1]:%08X\n",z[1]); - //printf ("z[2]:%08X\n",z[2]); - //printf ("z[3]:%08X\n",z[3]); - //printf ("z[4]:%08X\n",z[4]); - P = ((uint64_t)z[0] << 32) | (uint64_t)z[1]; - Q = ((uint64_t)z[2] << 32) | (uint64_t)z[3]; - //printf ("P:%16lX\n",P); - //printf ("Q:%16lX\n",Q); - /* Calculation */ - D = ceil( stream_cipher->blength / 64.0 ) + 1; - //printf ("D:%d\n",D); - EVAL = 0; - c = 0x1b; - - AssertFatal(stream_cipher->blength % 8 == 0, "unsupported buffer length\n"); - - uint8_t *message = stream_cipher->message; - - /* for 0 <= i <= D-3 */ - for (i=0; iblength % 64; - - if (rem_bits == 0) - rem_bits = 64; - - M_D_2 = U64(&message[4 * (2*(D-2))], rem_bits/8); - - V = EVAL ^ M_D_2; - EVAL = MUL64(V,P,c); - /* for D-1 */ - EVAL ^= stream_cipher->blength; - /* Multiply by Q */ - EVAL = MUL64(EVAL,Q,c); - MAC_I = (uint32_t)(EVAL >> 32) ^ z[4]; - //printf ("MAC_I:%16X\n",MAC_I); - MAC_I = hton_int32(MAC_I); - memcpy(out, &MAC_I, 4); + uint8_t *key = (uint8_t *)stream_cipher->context; + snow3g_integrity(stream_cipher->count, + stream_cipher->bearer, + stream_cipher->direction, + key, + stream_cipher->blength / 8, + stream_cipher->message, + out); } stream_security_context_t *stream_integrity_init_eia1(const uint8_t *integrity_key) diff --git a/openair3/SECU/snow3g.c b/openair3/SECU/snow3g.c index faab013541..2594ead431 100644 --- a/openair3/SECU/snow3g.c +++ b/openair3/SECU/snow3g.c @@ -19,326 +19,851 @@ * contact@openairinterface.org */ -#include -#include -#include -#include - -#include "rijndael.h" +#define NO_MAIN #include "snow3g.h" -static uint8_t _MULx(uint8_t V, uint8_t c); -static uint8_t _MULxPOW(uint8_t V, uint8_t i, uint8_t c); -static uint32_t _MULalpha(uint8_t c); -static uint32_t _DIValpha(uint8_t c); -static uint32_t _S1(uint32_t w); -static uint32_t _S2(uint32_t w); -static void _snow3g_clock_LFSR_initialization_mode(uint32_t F, snow_3g_context_t *s3g_ctx_pP); -static void _snow3g_clock_LFSR_key_stream_mode(snow_3g_context_t *snow_3g_context_pP); -static uint32_t _snow3g_clock_fsm(snow_3g_context_t *snow_3g_context_pP); -void snow3g_initialize(uint32_t k[4], uint32_t IV[4], snow_3g_context_t *snow_3g_context_pP); -void snow3g_generate_key_stream(uint32_t n, uint32_t *ks, snow_3g_context_t *snow_3g_context_pP); +#include +#include +typedef struct { + /* _s is twice as big as defined in the specs to avoid moving memory, + * we only change the pointer 's', see lfsr_keystream() + */ + uint32_t _s[16 * 2]; + uint32_t *s; + uint32_t r1, r2, r3; +} snow3g_t; -/* _MULx. -* Input V: an 8-bit input. -* Input c: an 8-bit input. -* Output : an 8-bit input. -* MULx maps 16 bits to 8 bits -*/ +static const uint32_t s1_t0[256] = { + 0xA56363C6, 0x847C7CF8, 0x997777EE, 0x8D7B7BF6, 0xDF2F2FF, 0xBD6B6BD6, 0xB16F6FDE, 0x54C5C591, + 0x50303060, 0x3010102, 0xA96767CE, 0x7D2B2B56, 0x19FEFEE7, 0x62D7D7B5, 0xE6ABAB4D, 0x9A7676EC, + 0x45CACA8F, 0x9D82821F, 0x40C9C989, 0x877D7DFA, 0x15FAFAEF, 0xEB5959B2, 0xC947478E, 0xBF0F0FB, + 0xECADAD41, 0x67D4D4B3, 0xFDA2A25F, 0xEAAFAF45, 0xBF9C9C23, 0xF7A4A453, 0x967272E4, 0x5BC0C09B, + 0xC2B7B775, 0x1CFDFDE1, 0xAE93933D, 0x6A26264C, 0x5A36366C, 0x413F3F7E, 0x2F7F7F5, 0x4FCCCC83, + 0x5C343468, 0xF4A5A551, 0x34E5E5D1, 0x8F1F1F9, 0x937171E2, 0x73D8D8AB, 0x53313162, 0x3F15152A, + 0xC040408, 0x52C7C795, 0x65232346, 0x5EC3C39D, 0x28181830, 0xA1969637, 0xF05050A, 0xB59A9A2F, + 0x907070E, 0x36121224, 0x9B80801B, 0x3DE2E2DF, 0x26EBEBCD, 0x6927274E, 0xCDB2B27F, 0x9F7575EA, + 0x1B090912, 0x9E83831D, 0x742C2C58, 0x2E1A1A34, 0x2D1B1B36, 0xB26E6EDC, 0xEE5A5AB4, 0xFBA0A05B, + 0xF65252A4, 0x4D3B3B76, 0x61D6D6B7, 0xCEB3B37D, 0x7B292952, 0x3EE3E3DD, 0x712F2F5E, 0x97848413, + 0xF55353A6, 0x68D1D1B9, 0x0, 0x2CEDEDC1, 0x60202040, 0x1FFCFCE3, 0xC8B1B179, 0xED5B5BB6, + 0xBE6A6AD4, 0x46CBCB8D, 0xD9BEBE67, 0x4B393972, 0xDE4A4A94, 0xD44C4C98, 0xE85858B0, 0x4ACFCF85, + 0x6BD0D0BB, 0x2AEFEFC5, 0xE5AAAA4F, 0x16FBFBED, 0xC5434386, 0xD74D4D9A, 0x55333366, 0x94858511, + 0xCF45458A, 0x10F9F9E9, 0x6020204, 0x817F7FFE, 0xF05050A0, 0x443C3C78, 0xBA9F9F25, 0xE3A8A84B, + 0xF35151A2, 0xFEA3A35D, 0xC0404080, 0x8A8F8F05, 0xAD92923F, 0xBC9D9D21, 0x48383870, 0x4F5F5F1, + 0xDFBCBC63, 0xC1B6B677, 0x75DADAAF, 0x63212142, 0x30101020, 0x1AFFFFE5, 0xEF3F3FD, 0x6DD2D2BF, + 0x4CCDCD81, 0x140C0C18, 0x35131326, 0x2FECECC3, 0xE15F5FBE, 0xA2979735, 0xCC444488, 0x3917172E, + 0x57C4C493, 0xF2A7A755, 0x827E7EFC, 0x473D3D7A, 0xAC6464C8, 0xE75D5DBA, 0x2B191932, 0x957373E6, + 0xA06060C0, 0x98818119, 0xD14F4F9E, 0x7FDCDCA3, 0x66222244, 0x7E2A2A54, 0xAB90903B, 0x8388880B, + 0xCA46468C, 0x29EEEEC7, 0xD3B8B86B, 0x3C141428, 0x79DEDEA7, 0xE25E5EBC, 0x1D0B0B16, 0x76DBDBAD, + 0x3BE0E0DB, 0x56323264, 0x4E3A3A74, 0x1E0A0A14, 0xDB494992, 0xA06060C, 0x6C242448, 0xE45C5CB8, + 0x5DC2C29F, 0x6ED3D3BD, 0xEFACAC43, 0xA66262C4, 0xA8919139, 0xA4959531, 0x37E4E4D3, 0x8B7979F2, + 0x32E7E7D5, 0x43C8C88B, 0x5937376E, 0xB76D6DDA, 0x8C8D8D01, 0x64D5D5B1, 0xD24E4E9C, 0xE0A9A949, + 0xB46C6CD8, 0xFA5656AC, 0x7F4F4F3, 0x25EAEACF, 0xAF6565CA, 0x8E7A7AF4, 0xE9AEAE47, 0x18080810, + 0xD5BABA6F, 0x887878F0, 0x6F25254A, 0x722E2E5C, 0x241C1C38, 0xF1A6A657, 0xC7B4B473, 0x51C6C697, + 0x23E8E8CB, 0x7CDDDDA1, 0x9C7474E8, 0x211F1F3E, 0xDD4B4B96, 0xDCBDBD61, 0x868B8B0D, 0x858A8A0F, + 0x907070E0, 0x423E3E7C, 0xC4B5B571, 0xAA6666CC, 0xD8484890, 0x5030306, 0x1F6F6F7, 0x120E0E1C, + 0xA36161C2, 0x5F35356A, 0xF95757AE, 0xD0B9B969, 0x91868617, 0x58C1C199, 0x271D1D3A, 0xB99E9E27, + 0x38E1E1D9, 0x13F8F8EB, 0xB398982B, 0x33111122, 0xBB6969D2, 0x70D9D9A9, 0x898E8E07, 0xA7949433, + 0xB69B9B2D, 0x221E1E3C, 0x92878715, 0x20E9E9C9, 0x49CECE87, 0xFF5555AA, 0x78282850, 0x7ADFDFA5, + 0x8F8C8C03, 0xF8A1A159, 0x80898909, 0x170D0D1A, 0xDABFBF65, 0x31E6E6D7, 0xC6424284, 0xB86868D0, + 0xC3414182, 0xB0999929, 0x772D2D5A, 0x110F0F1E, 0xCBB0B07B, 0xFC5454A8, 0xD6BBBB6D, 0x3A16162C, +}; -static uint8_t _MULx(uint8_t V, uint8_t c) +static const uint32_t s1_t1[256] = { + 0x6363C6A5, 0x7C7CF884, 0x7777EE99, 0x7B7BF68D, 0xF2F2FF0D, 0x6B6BD6BD, 0x6F6FDEB1, 0xC5C59154, + 0x30306050, 0x1010203, 0x6767CEA9, 0x2B2B567D, 0xFEFEE719, 0xD7D7B562, 0xABAB4DE6, 0x7676EC9A, + 0xCACA8F45, 0x82821F9D, 0xC9C98940, 0x7D7DFA87, 0xFAFAEF15, 0x5959B2EB, 0x47478EC9, 0xF0F0FB0B, + 0xADAD41EC, 0xD4D4B367, 0xA2A25FFD, 0xAFAF45EA, 0x9C9C23BF, 0xA4A453F7, 0x7272E496, 0xC0C09B5B, + 0xB7B775C2, 0xFDFDE11C, 0x93933DAE, 0x26264C6A, 0x36366C5A, 0x3F3F7E41, 0xF7F7F502, 0xCCCC834F, + 0x3434685C, 0xA5A551F4, 0xE5E5D134, 0xF1F1F908, 0x7171E293, 0xD8D8AB73, 0x31316253, 0x15152A3F, + 0x404080C, 0xC7C79552, 0x23234665, 0xC3C39D5E, 0x18183028, 0x969637A1, 0x5050A0F, 0x9A9A2FB5, + 0x7070E09, 0x12122436, 0x80801B9B, 0xE2E2DF3D, 0xEBEBCD26, 0x27274E69, 0xB2B27FCD, 0x7575EA9F, + 0x909121B, 0x83831D9E, 0x2C2C5874, 0x1A1A342E, 0x1B1B362D, 0x6E6EDCB2, 0x5A5AB4EE, 0xA0A05BFB, + 0x5252A4F6, 0x3B3B764D, 0xD6D6B761, 0xB3B37DCE, 0x2929527B, 0xE3E3DD3E, 0x2F2F5E71, 0x84841397, + 0x5353A6F5, 0xD1D1B968, 0x0, 0xEDEDC12C, 0x20204060, 0xFCFCE31F, 0xB1B179C8, 0x5B5BB6ED, + 0x6A6AD4BE, 0xCBCB8D46, 0xBEBE67D9, 0x3939724B, 0x4A4A94DE, 0x4C4C98D4, 0x5858B0E8, 0xCFCF854A, + 0xD0D0BB6B, 0xEFEFC52A, 0xAAAA4FE5, 0xFBFBED16, 0x434386C5, 0x4D4D9AD7, 0x33336655, 0x85851194, + 0x45458ACF, 0xF9F9E910, 0x2020406, 0x7F7FFE81, 0x5050A0F0, 0x3C3C7844, 0x9F9F25BA, 0xA8A84BE3, + 0x5151A2F3, 0xA3A35DFE, 0x404080C0, 0x8F8F058A, 0x92923FAD, 0x9D9D21BC, 0x38387048, 0xF5F5F104, + 0xBCBC63DF, 0xB6B677C1, 0xDADAAF75, 0x21214263, 0x10102030, 0xFFFFE51A, 0xF3F3FD0E, 0xD2D2BF6D, + 0xCDCD814C, 0xC0C1814, 0x13132635, 0xECECC32F, 0x5F5FBEE1, 0x979735A2, 0x444488CC, 0x17172E39, + 0xC4C49357, 0xA7A755F2, 0x7E7EFC82, 0x3D3D7A47, 0x6464C8AC, 0x5D5DBAE7, 0x1919322B, 0x7373E695, + 0x6060C0A0, 0x81811998, 0x4F4F9ED1, 0xDCDCA37F, 0x22224466, 0x2A2A547E, 0x90903BAB, 0x88880B83, + 0x46468CCA, 0xEEEEC729, 0xB8B86BD3, 0x1414283C, 0xDEDEA779, 0x5E5EBCE2, 0xB0B161D, 0xDBDBAD76, + 0xE0E0DB3B, 0x32326456, 0x3A3A744E, 0xA0A141E, 0x494992DB, 0x6060C0A, 0x2424486C, 0x5C5CB8E4, + 0xC2C29F5D, 0xD3D3BD6E, 0xACAC43EF, 0x6262C4A6, 0x919139A8, 0x959531A4, 0xE4E4D337, 0x7979F28B, + 0xE7E7D532, 0xC8C88B43, 0x37376E59, 0x6D6DDAB7, 0x8D8D018C, 0xD5D5B164, 0x4E4E9CD2, 0xA9A949E0, + 0x6C6CD8B4, 0x5656ACFA, 0xF4F4F307, 0xEAEACF25, 0x6565CAAF, 0x7A7AF48E, 0xAEAE47E9, 0x8081018, + 0xBABA6FD5, 0x7878F088, 0x25254A6F, 0x2E2E5C72, 0x1C1C3824, 0xA6A657F1, 0xB4B473C7, 0xC6C69751, + 0xE8E8CB23, 0xDDDDA17C, 0x7474E89C, 0x1F1F3E21, 0x4B4B96DD, 0xBDBD61DC, 0x8B8B0D86, 0x8A8A0F85, + 0x7070E090, 0x3E3E7C42, 0xB5B571C4, 0x6666CCAA, 0x484890D8, 0x3030605, 0xF6F6F701, 0xE0E1C12, + 0x6161C2A3, 0x35356A5F, 0x5757AEF9, 0xB9B969D0, 0x86861791, 0xC1C19958, 0x1D1D3A27, 0x9E9E27B9, + 0xE1E1D938, 0xF8F8EB13, 0x98982BB3, 0x11112233, 0x6969D2BB, 0xD9D9A970, 0x8E8E0789, 0x949433A7, + 0x9B9B2DB6, 0x1E1E3C22, 0x87871592, 0xE9E9C920, 0xCECE8749, 0x5555AAFF, 0x28285078, 0xDFDFA57A, + 0x8C8C038F, 0xA1A159F8, 0x89890980, 0xD0D1A17, 0xBFBF65DA, 0xE6E6D731, 0x424284C6, 0x6868D0B8, + 0x414182C3, 0x999929B0, 0x2D2D5A77, 0xF0F1E11, 0xB0B07BCB, 0x5454A8FC, 0xBBBB6DD6, 0x16162C3A, +}; + +static const uint32_t s1_t2[256] = { + 0x63C6A563, 0x7CF8847C, 0x77EE9977, 0x7BF68D7B, 0xF2FF0DF2, 0x6BD6BD6B, 0x6FDEB16F, 0xC59154C5, + 0x30605030, 0x1020301, 0x67CEA967, 0x2B567D2B, 0xFEE719FE, 0xD7B562D7, 0xAB4DE6AB, 0x76EC9A76, + 0xCA8F45CA, 0x821F9D82, 0xC98940C9, 0x7DFA877D, 0xFAEF15FA, 0x59B2EB59, 0x478EC947, 0xF0FB0BF0, + 0xAD41ECAD, 0xD4B367D4, 0xA25FFDA2, 0xAF45EAAF, 0x9C23BF9C, 0xA453F7A4, 0x72E49672, 0xC09B5BC0, + 0xB775C2B7, 0xFDE11CFD, 0x933DAE93, 0x264C6A26, 0x366C5A36, 0x3F7E413F, 0xF7F502F7, 0xCC834FCC, + 0x34685C34, 0xA551F4A5, 0xE5D134E5, 0xF1F908F1, 0x71E29371, 0xD8AB73D8, 0x31625331, 0x152A3F15, + 0x4080C04, 0xC79552C7, 0x23466523, 0xC39D5EC3, 0x18302818, 0x9637A196, 0x50A0F05, 0x9A2FB59A, + 0x70E0907, 0x12243612, 0x801B9B80, 0xE2DF3DE2, 0xEBCD26EB, 0x274E6927, 0xB27FCDB2, 0x75EA9F75, + 0x9121B09, 0x831D9E83, 0x2C58742C, 0x1A342E1A, 0x1B362D1B, 0x6EDCB26E, 0x5AB4EE5A, 0xA05BFBA0, + 0x52A4F652, 0x3B764D3B, 0xD6B761D6, 0xB37DCEB3, 0x29527B29, 0xE3DD3EE3, 0x2F5E712F, 0x84139784, + 0x53A6F553, 0xD1B968D1, 0x0, 0xEDC12CED, 0x20406020, 0xFCE31FFC, 0xB179C8B1, 0x5BB6ED5B, + 0x6AD4BE6A, 0xCB8D46CB, 0xBE67D9BE, 0x39724B39, 0x4A94DE4A, 0x4C98D44C, 0x58B0E858, 0xCF854ACF, + 0xD0BB6BD0, 0xEFC52AEF, 0xAA4FE5AA, 0xFBED16FB, 0x4386C543, 0x4D9AD74D, 0x33665533, 0x85119485, + 0x458ACF45, 0xF9E910F9, 0x2040602, 0x7FFE817F, 0x50A0F050, 0x3C78443C, 0x9F25BA9F, 0xA84BE3A8, + 0x51A2F351, 0xA35DFEA3, 0x4080C040, 0x8F058A8F, 0x923FAD92, 0x9D21BC9D, 0x38704838, 0xF5F104F5, + 0xBC63DFBC, 0xB677C1B6, 0xDAAF75DA, 0x21426321, 0x10203010, 0xFFE51AFF, 0xF3FD0EF3, 0xD2BF6DD2, + 0xCD814CCD, 0xC18140C, 0x13263513, 0xECC32FEC, 0x5FBEE15F, 0x9735A297, 0x4488CC44, 0x172E3917, + 0xC49357C4, 0xA755F2A7, 0x7EFC827E, 0x3D7A473D, 0x64C8AC64, 0x5DBAE75D, 0x19322B19, 0x73E69573, + 0x60C0A060, 0x81199881, 0x4F9ED14F, 0xDCA37FDC, 0x22446622, 0x2A547E2A, 0x903BAB90, 0x880B8388, + 0x468CCA46, 0xEEC729EE, 0xB86BD3B8, 0x14283C14, 0xDEA779DE, 0x5EBCE25E, 0xB161D0B, 0xDBAD76DB, + 0xE0DB3BE0, 0x32645632, 0x3A744E3A, 0xA141E0A, 0x4992DB49, 0x60C0A06, 0x24486C24, 0x5CB8E45C, + 0xC29F5DC2, 0xD3BD6ED3, 0xAC43EFAC, 0x62C4A662, 0x9139A891, 0x9531A495, 0xE4D337E4, 0x79F28B79, + 0xE7D532E7, 0xC88B43C8, 0x376E5937, 0x6DDAB76D, 0x8D018C8D, 0xD5B164D5, 0x4E9CD24E, 0xA949E0A9, + 0x6CD8B46C, 0x56ACFA56, 0xF4F307F4, 0xEACF25EA, 0x65CAAF65, 0x7AF48E7A, 0xAE47E9AE, 0x8101808, + 0xBA6FD5BA, 0x78F08878, 0x254A6F25, 0x2E5C722E, 0x1C38241C, 0xA657F1A6, 0xB473C7B4, 0xC69751C6, + 0xE8CB23E8, 0xDDA17CDD, 0x74E89C74, 0x1F3E211F, 0x4B96DD4B, 0xBD61DCBD, 0x8B0D868B, 0x8A0F858A, + 0x70E09070, 0x3E7C423E, 0xB571C4B5, 0x66CCAA66, 0x4890D848, 0x3060503, 0xF6F701F6, 0xE1C120E, + 0x61C2A361, 0x356A5F35, 0x57AEF957, 0xB969D0B9, 0x86179186, 0xC19958C1, 0x1D3A271D, 0x9E27B99E, + 0xE1D938E1, 0xF8EB13F8, 0x982BB398, 0x11223311, 0x69D2BB69, 0xD9A970D9, 0x8E07898E, 0x9433A794, + 0x9B2DB69B, 0x1E3C221E, 0x87159287, 0xE9C920E9, 0xCE8749CE, 0x55AAFF55, 0x28507828, 0xDFA57ADF, + 0x8C038F8C, 0xA159F8A1, 0x89098089, 0xD1A170D, 0xBF65DABF, 0xE6D731E6, 0x4284C642, 0x68D0B868, + 0x4182C341, 0x9929B099, 0x2D5A772D, 0xF1E110F, 0xB07BCBB0, 0x54A8FC54, 0xBB6DD6BB, 0x162C3A16, +}; + +static const uint32_t s1_t3[256] = { + 0xC6A56363, 0xF8847C7C, 0xEE997777, 0xF68D7B7B, 0xFF0DF2F2, 0xD6BD6B6B, 0xDEB16F6F, 0x9154C5C5, + 0x60503030, 0x2030101, 0xCEA96767, 0x567D2B2B, 0xE719FEFE, 0xB562D7D7, 0x4DE6ABAB, 0xEC9A7676, + 0x8F45CACA, 0x1F9D8282, 0x8940C9C9, 0xFA877D7D, 0xEF15FAFA, 0xB2EB5959, 0x8EC94747, 0xFB0BF0F0, + 0x41ECADAD, 0xB367D4D4, 0x5FFDA2A2, 0x45EAAFAF, 0x23BF9C9C, 0x53F7A4A4, 0xE4967272, 0x9B5BC0C0, + 0x75C2B7B7, 0xE11CFDFD, 0x3DAE9393, 0x4C6A2626, 0x6C5A3636, 0x7E413F3F, 0xF502F7F7, 0x834FCCCC, + 0x685C3434, 0x51F4A5A5, 0xD134E5E5, 0xF908F1F1, 0xE2937171, 0xAB73D8D8, 0x62533131, 0x2A3F1515, + 0x80C0404, 0x9552C7C7, 0x46652323, 0x9D5EC3C3, 0x30281818, 0x37A19696, 0xA0F0505, 0x2FB59A9A, + 0xE090707, 0x24361212, 0x1B9B8080, 0xDF3DE2E2, 0xCD26EBEB, 0x4E692727, 0x7FCDB2B2, 0xEA9F7575, + 0x121B0909, 0x1D9E8383, 0x58742C2C, 0x342E1A1A, 0x362D1B1B, 0xDCB26E6E, 0xB4EE5A5A, 0x5BFBA0A0, + 0xA4F65252, 0x764D3B3B, 0xB761D6D6, 0x7DCEB3B3, 0x527B2929, 0xDD3EE3E3, 0x5E712F2F, 0x13978484, + 0xA6F55353, 0xB968D1D1, 0x0, 0xC12CEDED, 0x40602020, 0xE31FFCFC, 0x79C8B1B1, 0xB6ED5B5B, + 0xD4BE6A6A, 0x8D46CBCB, 0x67D9BEBE, 0x724B3939, 0x94DE4A4A, 0x98D44C4C, 0xB0E85858, 0x854ACFCF, + 0xBB6BD0D0, 0xC52AEFEF, 0x4FE5AAAA, 0xED16FBFB, 0x86C54343, 0x9AD74D4D, 0x66553333, 0x11948585, + 0x8ACF4545, 0xE910F9F9, 0x4060202, 0xFE817F7F, 0xA0F05050, 0x78443C3C, 0x25BA9F9F, 0x4BE3A8A8, + 0xA2F35151, 0x5DFEA3A3, 0x80C04040, 0x58A8F8F, 0x3FAD9292, 0x21BC9D9D, 0x70483838, 0xF104F5F5, + 0x63DFBCBC, 0x77C1B6B6, 0xAF75DADA, 0x42632121, 0x20301010, 0xE51AFFFF, 0xFD0EF3F3, 0xBF6DD2D2, + 0x814CCDCD, 0x18140C0C, 0x26351313, 0xC32FECEC, 0xBEE15F5F, 0x35A29797, 0x88CC4444, 0x2E391717, + 0x9357C4C4, 0x55F2A7A7, 0xFC827E7E, 0x7A473D3D, 0xC8AC6464, 0xBAE75D5D, 0x322B1919, 0xE6957373, + 0xC0A06060, 0x19988181, 0x9ED14F4F, 0xA37FDCDC, 0x44662222, 0x547E2A2A, 0x3BAB9090, 0xB838888, + 0x8CCA4646, 0xC729EEEE, 0x6BD3B8B8, 0x283C1414, 0xA779DEDE, 0xBCE25E5E, 0x161D0B0B, 0xAD76DBDB, + 0xDB3BE0E0, 0x64563232, 0x744E3A3A, 0x141E0A0A, 0x92DB4949, 0xC0A0606, 0x486C2424, 0xB8E45C5C, + 0x9F5DC2C2, 0xBD6ED3D3, 0x43EFACAC, 0xC4A66262, 0x39A89191, 0x31A49595, 0xD337E4E4, 0xF28B7979, + 0xD532E7E7, 0x8B43C8C8, 0x6E593737, 0xDAB76D6D, 0x18C8D8D, 0xB164D5D5, 0x9CD24E4E, 0x49E0A9A9, + 0xD8B46C6C, 0xACFA5656, 0xF307F4F4, 0xCF25EAEA, 0xCAAF6565, 0xF48E7A7A, 0x47E9AEAE, 0x10180808, + 0x6FD5BABA, 0xF0887878, 0x4A6F2525, 0x5C722E2E, 0x38241C1C, 0x57F1A6A6, 0x73C7B4B4, 0x9751C6C6, + 0xCB23E8E8, 0xA17CDDDD, 0xE89C7474, 0x3E211F1F, 0x96DD4B4B, 0x61DCBDBD, 0xD868B8B, 0xF858A8A, + 0xE0907070, 0x7C423E3E, 0x71C4B5B5, 0xCCAA6666, 0x90D84848, 0x6050303, 0xF701F6F6, 0x1C120E0E, + 0xC2A36161, 0x6A5F3535, 0xAEF95757, 0x69D0B9B9, 0x17918686, 0x9958C1C1, 0x3A271D1D, 0x27B99E9E, + 0xD938E1E1, 0xEB13F8F8, 0x2BB39898, 0x22331111, 0xD2BB6969, 0xA970D9D9, 0x7898E8E, 0x33A79494, + 0x2DB69B9B, 0x3C221E1E, 0x15928787, 0xC920E9E9, 0x8749CECE, 0xAAFF5555, 0x50782828, 0xA57ADFDF, + 0x38F8C8C, 0x59F8A1A1, 0x9808989, 0x1A170D0D, 0x65DABFBF, 0xD731E6E6, 0x84C64242, 0xD0B86868, + 0x82C34141, 0x29B09999, 0x5A772D2D, 0x1E110F0F, 0x7BCBB0B0, 0xA8FC5454, 0x6DD6BBBB, 0x2C3A1616, +}; + +static uint32_t s1(uint32_t w) { - //If the leftmost (i.e. the most significant) bit of V equals 1 - if ( V & 0x80 ) - return ( (V << 1) ^ c); - else - return ( V << 1); + int w0 = (w >> 24) & 0xff; + int w1 = (w >> 16) & 0xff; + int w2 = (w >> 8) & 0xff; + int w3 = w & 0xff; + + return s1_t0[w3] ^ s1_t1[w2] ^ s1_t2[w1] ^ s1_t3[w0]; } -/* _MULxPOW. -* Input V: an 8-bit input. -* Input i: a positive integer. -* Input c: an 8-bit input. -* Output : an 8-bit output. -* MULxPOW maps 16 bits and a positive integer i to 8 bit. -*/ +static const uint32_t s2_t0[256] = { + 0x6f25254a, 0x6c242448, 0x957373e6, 0xa96767ce, 0x10d7d7c7, 0x9baeae35, 0xe45c5cb8, 0x50303060, + 0x85a4a421, 0x5beeeeb5, 0xb26e6edc, 0x34cbcbff, 0x877d7dfa, 0xb6b5b503, 0xef82826d, 0x04dbdbdf, + 0x45e4e4a1, 0xfb8e8e75, 0xd8484890, 0xdb494992, 0xd14f4f9e, 0xe75d5dba, 0xbe6a6ad4, 0x887878f0, + 0x907070e0, 0xf1888879, 0x51e8e8b9, 0xe15f5fbe, 0xe25e5ebc, 0xe5848461, 0xaf6565ca, 0x4fe2e2ad, + 0x01d8d8d9, 0x52e9e9bb, 0x3dccccf1, 0x5eededb3, 0xc0404080, 0x712f2f5e, 0x33111122, 0x78282850, + 0xf95757ae, 0x1fd2d2cd, 0x9dacac31, 0x4ce3e3af, 0xde4a4a94, 0x3f15152a, 0x2d1b1b36, 0xa2b9b91b, + 0xbfb2b20d, 0xe9808069, 0xe6858563, 0x83a6a625, 0x722e2e5c, 0x06020204, 0xc947478e, 0x7b292952, + 0x0907070e, 0xdd4b4b96, 0x120e0e1c, 0x2ac1c1eb, 0xf35151a2, 0x97aaaa3d, 0xf289897b, 0x15d4d4c1, + 0x37cacafd, 0x03010102, 0xca46468c, 0xbcb3b30f, 0x58efefb7, 0x0eddddd3, 0xcc444488, 0x8d7b7bf6, + 0x2fc2c2ed, 0x817f7ffe, 0xabbebe15, 0x2cc3c3ef, 0xc89f9f57, 0x60202040, 0xd44c4c98, 0xac6464c8, + 0xec83836f, 0x8fa2a22d, 0xb86868d0, 0xc6424284, 0x35131326, 0xb5b4b401, 0xc3414182, 0x3ecdcdf3, + 0xa7baba1d, 0x23c6c6e5, 0xa4bbbb1f, 0xb76d6dda, 0xd74d4d9a, 0x937171e2, 0x63212142, 0x75f4f481, + 0xfe8d8d73, 0xb9b0b009, 0x46e5e5a3, 0xdc93934f, 0x6bfefe95, 0xf88f8f77, 0x43e6e6a5, 0x38cfcff7, + 0xc5434386, 0xcf45458a, 0x53313162, 0x66222244, 0x5937376e, 0x5a36366c, 0xd3969645, 0x67fafa9d, + 0xadbcbc11, 0x110f0f1e, 0x18080810, 0xf65252a4, 0x271d1d3a, 0xff5555aa, 0x2e1a1a34, 0x26c5c5e3, + 0xd24e4e9c, 0x65232346, 0xbb6969d2, 0x8e7a7af4, 0xdf92924d, 0x68ffff97, 0xed5b5bb6, 0xee5a5ab4, + 0x54ebebbf, 0xc79a9a5d, 0x241c1c38, 0x92a9a93b, 0x1ad1d1cb, 0x827e7efc, 0x170d0d1a, 0x6dfcfc91, + 0xf05050a0, 0xf78a8a7d, 0xb3b6b605, 0xa66262c4, 0x76f5f583, 0x1e0a0a14, 0x61f8f899, 0x0ddcdcd1, + 0x05030306, 0x443c3c78, 0x140c0c18, 0x4b393972, 0x7af1f18b, 0xa1b8b819, 0x7cf3f38f, 0x473d3d7a, + 0x7ff2f28d, 0x16d5d5c3, 0xd0979747, 0xaa6666cc, 0xea81816b, 0x56323264, 0x89a0a029, 0x00000000, + 0x0a06060c, 0x3bcecef5, 0x73f6f685, 0x57eaeabd, 0xb0b7b707, 0x3917172e, 0x70f7f787, 0xfd8c8c71, + 0x8b7979f2, 0x13d6d6c5, 0x80a7a727, 0xa8bfbf17, 0xf48b8b7f, 0x413f3f7e, 0x211f1f3e, 0xf55353a6, + 0xa56363c6, 0x9f7575ea, 0x5f35356a, 0x742c2c58, 0xa06060c0, 0x6efdfd93, 0x6927274e, 0x1cd3d3cf, + 0xd5949441, 0x86a5a523, 0x847c7cf8, 0x8aa1a12b, 0x0f05050a, 0xe85858b0, 0x772d2d5a, 0xaebdbd13, + 0x02d9d9db, 0x20c7c7e7, 0x98afaf37, 0xbd6b6bd6, 0xfc5454a8, 0x1d0b0b16, 0x49e0e0a9, 0x48383870, + 0x0c040408, 0x31c8c8f9, 0xce9d9d53, 0x40e7e7a7, 0x3c141428, 0xbab1b10b, 0xe0878767, 0xcd9c9c51, + 0x08dfdfd7, 0xb16f6fde, 0x62f9f99b, 0x07dadadd, 0x7e2a2a54, 0x25c4c4e1, 0xeb5959b2, 0x3a16162c, + 0x9c7474e8, 0xda91914b, 0x94abab3f, 0x6a26264c, 0xa36161c2, 0x9a7676ec, 0x5c343468, 0x7d2b2b56, + 0x9eadad33, 0xc299995b, 0x64fbfb9f, 0x967272e4, 0x5dececb1, 0x55333366, 0x36121224, 0x0bdeded5, + 0xc1989859, 0x4d3b3b76, 0x29c0c0e9, 0xc49b9b5f, 0x423e3e7c, 0x28181830, 0x30101020, 0x4e3a3a74, + 0xfa5656ac, 0x4ae1e1ab, 0x997777ee, 0x32c9c9fb, 0x221e1e3c, 0xcb9e9e55, 0xd6959543, 0x8ca3a32f, + 0xd9909049, 0x2b191932, 0x91a8a839, 0xb46c6cd8, 0x1b090912, 0x19d0d0c9, 0x79f0f089, 0xe3868665, +}; -static uint8_t _MULxPOW(uint8_t V, uint8_t i, uint8_t c) +static const uint32_t s2_t1[256] = { + 0x25254a6f, 0x2424486c, 0x7373e695, 0x6767cea9, 0xd7d7c710, 0xaeae359b, 0x5c5cb8e4, 0x30306050, + 0xa4a42185, 0xeeeeb55b, 0x6e6edcb2, 0xcbcbff34, 0x7d7dfa87, 0xb5b503b6, 0x82826def, 0xdbdbdf04, + 0xe4e4a145, 0x8e8e75fb, 0x484890d8, 0x494992db, 0x4f4f9ed1, 0x5d5dbae7, 0x6a6ad4be, 0x7878f088, + 0x7070e090, 0x888879f1, 0xe8e8b951, 0x5f5fbee1, 0x5e5ebce2, 0x848461e5, 0x6565caaf, 0xe2e2ad4f, + 0xd8d8d901, 0xe9e9bb52, 0xccccf13d, 0xededb35e, 0x404080c0, 0x2f2f5e71, 0x11112233, 0x28285078, + 0x5757aef9, 0xd2d2cd1f, 0xacac319d, 0xe3e3af4c, 0x4a4a94de, 0x15152a3f, 0x1b1b362d, 0xb9b91ba2, + 0xb2b20dbf, 0x808069e9, 0x858563e6, 0xa6a62583, 0x2e2e5c72, 0x02020406, 0x47478ec9, 0x2929527b, + 0x07070e09, 0x4b4b96dd, 0x0e0e1c12, 0xc1c1eb2a, 0x5151a2f3, 0xaaaa3d97, 0x89897bf2, 0xd4d4c115, + 0xcacafd37, 0x01010203, 0x46468cca, 0xb3b30fbc, 0xefefb758, 0xddddd30e, 0x444488cc, 0x7b7bf68d, + 0xc2c2ed2f, 0x7f7ffe81, 0xbebe15ab, 0xc3c3ef2c, 0x9f9f57c8, 0x20204060, 0x4c4c98d4, 0x6464c8ac, + 0x83836fec, 0xa2a22d8f, 0x6868d0b8, 0x424284c6, 0x13132635, 0xb4b401b5, 0x414182c3, 0xcdcdf33e, + 0xbaba1da7, 0xc6c6e523, 0xbbbb1fa4, 0x6d6ddab7, 0x4d4d9ad7, 0x7171e293, 0x21214263, 0xf4f48175, + 0x8d8d73fe, 0xb0b009b9, 0xe5e5a346, 0x93934fdc, 0xfefe956b, 0x8f8f77f8, 0xe6e6a543, 0xcfcff738, + 0x434386c5, 0x45458acf, 0x31316253, 0x22224466, 0x37376e59, 0x36366c5a, 0x969645d3, 0xfafa9d67, + 0xbcbc11ad, 0x0f0f1e11, 0x08081018, 0x5252a4f6, 0x1d1d3a27, 0x5555aaff, 0x1a1a342e, 0xc5c5e326, + 0x4e4e9cd2, 0x23234665, 0x6969d2bb, 0x7a7af48e, 0x92924ddf, 0xffff9768, 0x5b5bb6ed, 0x5a5ab4ee, + 0xebebbf54, 0x9a9a5dc7, 0x1c1c3824, 0xa9a93b92, 0xd1d1cb1a, 0x7e7efc82, 0x0d0d1a17, 0xfcfc916d, + 0x5050a0f0, 0x8a8a7df7, 0xb6b605b3, 0x6262c4a6, 0xf5f58376, 0x0a0a141e, 0xf8f89961, 0xdcdcd10d, + 0x03030605, 0x3c3c7844, 0x0c0c1814, 0x3939724b, 0xf1f18b7a, 0xb8b819a1, 0xf3f38f7c, 0x3d3d7a47, + 0xf2f28d7f, 0xd5d5c316, 0x979747d0, 0x6666ccaa, 0x81816bea, 0x32326456, 0xa0a02989, 0x00000000, + 0x06060c0a, 0xcecef53b, 0xf6f68573, 0xeaeabd57, 0xb7b707b0, 0x17172e39, 0xf7f78770, 0x8c8c71fd, + 0x7979f28b, 0xd6d6c513, 0xa7a72780, 0xbfbf17a8, 0x8b8b7ff4, 0x3f3f7e41, 0x1f1f3e21, 0x5353a6f5, + 0x6363c6a5, 0x7575ea9f, 0x35356a5f, 0x2c2c5874, 0x6060c0a0, 0xfdfd936e, 0x27274e69, 0xd3d3cf1c, + 0x949441d5, 0xa5a52386, 0x7c7cf884, 0xa1a12b8a, 0x05050a0f, 0x5858b0e8, 0x2d2d5a77, 0xbdbd13ae, + 0xd9d9db02, 0xc7c7e720, 0xafaf3798, 0x6b6bd6bd, 0x5454a8fc, 0x0b0b161d, 0xe0e0a949, 0x38387048, + 0x0404080c, 0xc8c8f931, 0x9d9d53ce, 0xe7e7a740, 0x1414283c, 0xb1b10bba, 0x878767e0, 0x9c9c51cd, + 0xdfdfd708, 0x6f6fdeb1, 0xf9f99b62, 0xdadadd07, 0x2a2a547e, 0xc4c4e125, 0x5959b2eb, 0x16162c3a, + 0x7474e89c, 0x91914bda, 0xabab3f94, 0x26264c6a, 0x6161c2a3, 0x7676ec9a, 0x3434685c, 0x2b2b567d, + 0xadad339e, 0x99995bc2, 0xfbfb9f64, 0x7272e496, 0xececb15d, 0x33336655, 0x12122436, 0xdeded50b, + 0x989859c1, 0x3b3b764d, 0xc0c0e929, 0x9b9b5fc4, 0x3e3e7c42, 0x18183028, 0x10102030, 0x3a3a744e, + 0x5656acfa, 0xe1e1ab4a, 0x7777ee99, 0xc9c9fb32, 0x1e1e3c22, 0x9e9e55cb, 0x959543d6, 0xa3a32f8c, + 0x909049d9, 0x1919322b, 0xa8a83991, 0x6c6cd8b4, 0x0909121b, 0xd0d0c919, 0xf0f08979, 0x868665e3, +}; + +static const uint32_t s2_t2[256] = { + 0x254a6f25, 0x24486c24, 0x73e69573, 0x67cea967, 0xd7c710d7, 0xae359bae, 0x5cb8e45c, 0x30605030, + 0xa42185a4, 0xeeb55bee, 0x6edcb26e, 0xcbff34cb, 0x7dfa877d, 0xb503b6b5, 0x826def82, 0xdbdf04db, + 0xe4a145e4, 0x8e75fb8e, 0x4890d848, 0x4992db49, 0x4f9ed14f, 0x5dbae75d, 0x6ad4be6a, 0x78f08878, + 0x70e09070, 0x8879f188, 0xe8b951e8, 0x5fbee15f, 0x5ebce25e, 0x8461e584, 0x65caaf65, 0xe2ad4fe2, + 0xd8d901d8, 0xe9bb52e9, 0xccf13dcc, 0xedb35eed, 0x4080c040, 0x2f5e712f, 0x11223311, 0x28507828, + 0x57aef957, 0xd2cd1fd2, 0xac319dac, 0xe3af4ce3, 0x4a94de4a, 0x152a3f15, 0x1b362d1b, 0xb91ba2b9, + 0xb20dbfb2, 0x8069e980, 0x8563e685, 0xa62583a6, 0x2e5c722e, 0x02040602, 0x478ec947, 0x29527b29, + 0x070e0907, 0x4b96dd4b, 0x0e1c120e, 0xc1eb2ac1, 0x51a2f351, 0xaa3d97aa, 0x897bf289, 0xd4c115d4, + 0xcafd37ca, 0x01020301, 0x468cca46, 0xb30fbcb3, 0xefb758ef, 0xddd30edd, 0x4488cc44, 0x7bf68d7b, + 0xc2ed2fc2, 0x7ffe817f, 0xbe15abbe, 0xc3ef2cc3, 0x9f57c89f, 0x20406020, 0x4c98d44c, 0x64c8ac64, + 0x836fec83, 0xa22d8fa2, 0x68d0b868, 0x4284c642, 0x13263513, 0xb401b5b4, 0x4182c341, 0xcdf33ecd, + 0xba1da7ba, 0xc6e523c6, 0xbb1fa4bb, 0x6ddab76d, 0x4d9ad74d, 0x71e29371, 0x21426321, 0xf48175f4, + 0x8d73fe8d, 0xb009b9b0, 0xe5a346e5, 0x934fdc93, 0xfe956bfe, 0x8f77f88f, 0xe6a543e6, 0xcff738cf, + 0x4386c543, 0x458acf45, 0x31625331, 0x22446622, 0x376e5937, 0x366c5a36, 0x9645d396, 0xfa9d67fa, + 0xbc11adbc, 0x0f1e110f, 0x08101808, 0x52a4f652, 0x1d3a271d, 0x55aaff55, 0x1a342e1a, 0xc5e326c5, + 0x4e9cd24e, 0x23466523, 0x69d2bb69, 0x7af48e7a, 0x924ddf92, 0xff9768ff, 0x5bb6ed5b, 0x5ab4ee5a, + 0xebbf54eb, 0x9a5dc79a, 0x1c38241c, 0xa93b92a9, 0xd1cb1ad1, 0x7efc827e, 0x0d1a170d, 0xfc916dfc, + 0x50a0f050, 0x8a7df78a, 0xb605b3b6, 0x62c4a662, 0xf58376f5, 0x0a141e0a, 0xf89961f8, 0xdcd10ddc, + 0x03060503, 0x3c78443c, 0x0c18140c, 0x39724b39, 0xf18b7af1, 0xb819a1b8, 0xf38f7cf3, 0x3d7a473d, + 0xf28d7ff2, 0xd5c316d5, 0x9747d097, 0x66ccaa66, 0x816bea81, 0x32645632, 0xa02989a0, 0x00000000, + 0x060c0a06, 0xcef53bce, 0xf68573f6, 0xeabd57ea, 0xb707b0b7, 0x172e3917, 0xf78770f7, 0x8c71fd8c, + 0x79f28b79, 0xd6c513d6, 0xa72780a7, 0xbf17a8bf, 0x8b7ff48b, 0x3f7e413f, 0x1f3e211f, 0x53a6f553, + 0x63c6a563, 0x75ea9f75, 0x356a5f35, 0x2c58742c, 0x60c0a060, 0xfd936efd, 0x274e6927, 0xd3cf1cd3, + 0x9441d594, 0xa52386a5, 0x7cf8847c, 0xa12b8aa1, 0x050a0f05, 0x58b0e858, 0x2d5a772d, 0xbd13aebd, + 0xd9db02d9, 0xc7e720c7, 0xaf3798af, 0x6bd6bd6b, 0x54a8fc54, 0x0b161d0b, 0xe0a949e0, 0x38704838, + 0x04080c04, 0xc8f931c8, 0x9d53ce9d, 0xe7a740e7, 0x14283c14, 0xb10bbab1, 0x8767e087, 0x9c51cd9c, + 0xdfd708df, 0x6fdeb16f, 0xf99b62f9, 0xdadd07da, 0x2a547e2a, 0xc4e125c4, 0x59b2eb59, 0x162c3a16, + 0x74e89c74, 0x914bda91, 0xab3f94ab, 0x264c6a26, 0x61c2a361, 0x76ec9a76, 0x34685c34, 0x2b567d2b, + 0xad339ead, 0x995bc299, 0xfb9f64fb, 0x72e49672, 0xecb15dec, 0x33665533, 0x12243612, 0xded50bde, + 0x9859c198, 0x3b764d3b, 0xc0e929c0, 0x9b5fc49b, 0x3e7c423e, 0x18302818, 0x10203010, 0x3a744e3a, + 0x56acfa56, 0xe1ab4ae1, 0x77ee9977, 0xc9fb32c9, 0x1e3c221e, 0x9e55cb9e, 0x9543d695, 0xa32f8ca3, + 0x9049d990, 0x19322b19, 0xa83991a8, 0x6cd8b46c, 0x09121b09, 0xd0c919d0, 0xf08979f0, 0x8665e386, +}; + +static const uint32_t s2_t3[256] = { + 0x4a6f2525, 0x486c2424, 0xe6957373, 0xcea96767, 0xc710d7d7, 0x359baeae, 0xb8e45c5c, 0x60503030, + 0x2185a4a4, 0xb55beeee, 0xdcb26e6e, 0xff34cbcb, 0xfa877d7d, 0x03b6b5b5, 0x6def8282, 0xdf04dbdb, + 0xa145e4e4, 0x75fb8e8e, 0x90d84848, 0x92db4949, 0x9ed14f4f, 0xbae75d5d, 0xd4be6a6a, 0xf0887878, + 0xe0907070, 0x79f18888, 0xb951e8e8, 0xbee15f5f, 0xbce25e5e, 0x61e58484, 0xcaaf6565, 0xad4fe2e2, + 0xd901d8d8, 0xbb52e9e9, 0xf13dcccc, 0xb35eeded, 0x80c04040, 0x5e712f2f, 0x22331111, 0x50782828, + 0xaef95757, 0xcd1fd2d2, 0x319dacac, 0xaf4ce3e3, 0x94de4a4a, 0x2a3f1515, 0x362d1b1b, 0x1ba2b9b9, + 0x0dbfb2b2, 0x69e98080, 0x63e68585, 0x2583a6a6, 0x5c722e2e, 0x04060202, 0x8ec94747, 0x527b2929, + 0x0e090707, 0x96dd4b4b, 0x1c120e0e, 0xeb2ac1c1, 0xa2f35151, 0x3d97aaaa, 0x7bf28989, 0xc115d4d4, + 0xfd37caca, 0x02030101, 0x8cca4646, 0x0fbcb3b3, 0xb758efef, 0xd30edddd, 0x88cc4444, 0xf68d7b7b, + 0xed2fc2c2, 0xfe817f7f, 0x15abbebe, 0xef2cc3c3, 0x57c89f9f, 0x40602020, 0x98d44c4c, 0xc8ac6464, + 0x6fec8383, 0x2d8fa2a2, 0xd0b86868, 0x84c64242, 0x26351313, 0x01b5b4b4, 0x82c34141, 0xf33ecdcd, + 0x1da7baba, 0xe523c6c6, 0x1fa4bbbb, 0xdab76d6d, 0x9ad74d4d, 0xe2937171, 0x42632121, 0x8175f4f4, + 0x73fe8d8d, 0x09b9b0b0, 0xa346e5e5, 0x4fdc9393, 0x956bfefe, 0x77f88f8f, 0xa543e6e6, 0xf738cfcf, + 0x86c54343, 0x8acf4545, 0x62533131, 0x44662222, 0x6e593737, 0x6c5a3636, 0x45d39696, 0x9d67fafa, + 0x11adbcbc, 0x1e110f0f, 0x10180808, 0xa4f65252, 0x3a271d1d, 0xaaff5555, 0x342e1a1a, 0xe326c5c5, + 0x9cd24e4e, 0x46652323, 0xd2bb6969, 0xf48e7a7a, 0x4ddf9292, 0x9768ffff, 0xb6ed5b5b, 0xb4ee5a5a, + 0xbf54ebeb, 0x5dc79a9a, 0x38241c1c, 0x3b92a9a9, 0xcb1ad1d1, 0xfc827e7e, 0x1a170d0d, 0x916dfcfc, + 0xa0f05050, 0x7df78a8a, 0x05b3b6b6, 0xc4a66262, 0x8376f5f5, 0x141e0a0a, 0x9961f8f8, 0xd10ddcdc, + 0x06050303, 0x78443c3c, 0x18140c0c, 0x724b3939, 0x8b7af1f1, 0x19a1b8b8, 0x8f7cf3f3, 0x7a473d3d, + 0x8d7ff2f2, 0xc316d5d5, 0x47d09797, 0xccaa6666, 0x6bea8181, 0x64563232, 0x2989a0a0, 0x00000000, + 0x0c0a0606, 0xf53bcece, 0x8573f6f6, 0xbd57eaea, 0x07b0b7b7, 0x2e391717, 0x8770f7f7, 0x71fd8c8c, + 0xf28b7979, 0xc513d6d6, 0x2780a7a7, 0x17a8bfbf, 0x7ff48b8b, 0x7e413f3f, 0x3e211f1f, 0xa6f55353, + 0xc6a56363, 0xea9f7575, 0x6a5f3535, 0x58742c2c, 0xc0a06060, 0x936efdfd, 0x4e692727, 0xcf1cd3d3, + 0x41d59494, 0x2386a5a5, 0xf8847c7c, 0x2b8aa1a1, 0x0a0f0505, 0xb0e85858, 0x5a772d2d, 0x13aebdbd, + 0xdb02d9d9, 0xe720c7c7, 0x3798afaf, 0xd6bd6b6b, 0xa8fc5454, 0x161d0b0b, 0xa949e0e0, 0x70483838, + 0x080c0404, 0xf931c8c8, 0x53ce9d9d, 0xa740e7e7, 0x283c1414, 0x0bbab1b1, 0x67e08787, 0x51cd9c9c, + 0xd708dfdf, 0xdeb16f6f, 0x9b62f9f9, 0xdd07dada, 0x547e2a2a, 0xe125c4c4, 0xb2eb5959, 0x2c3a1616, + 0xe89c7474, 0x4bda9191, 0x3f94abab, 0x4c6a2626, 0xc2a36161, 0xec9a7676, 0x685c3434, 0x567d2b2b, + 0x339eadad, 0x5bc29999, 0x9f64fbfb, 0xe4967272, 0xb15decec, 0x66553333, 0x24361212, 0xd50bdede, + 0x59c19898, 0x764d3b3b, 0xe929c0c0, 0x5fc49b9b, 0x7c423e3e, 0x30281818, 0x20301010, 0x744e3a3a, + 0xacfa5656, 0xab4ae1e1, 0xee997777, 0xfb32c9c9, 0x3c221e1e, 0x55cb9e9e, 0x43d69595, 0x2f8ca3a3, + 0x49d99090, 0x322b1919, 0x3991a8a8, 0xd8b46c6c, 0x121b0909, 0xc919d0d0, 0x8979f0f0, 0x65e38686, +}; + +static uint32_t s2(uint32_t w) { - if ( i == 0) - return V; - else - return _MULx( _MULxPOW( V, i-1, c ), c); + int w0 = (w >> 24) & 0xff; + int w1 = (w >> 16) & 0xff; + int w2 = (w >> 8) & 0xff; + int w3 = w & 0xff; + + return s2_t0[w3] ^ s2_t1[w2] ^ s2_t2[w1] ^ s2_t3[w0]; } -/* The function _MULalpha. -* Input c: 8-bit input. -* Output : 32-bit output. -* maps 8 bits to 32 bits. -*/ +static const uint32_t mula[256] = { + 0x00000000, 0xE19FCF13, 0x6B973726, 0x8A08F835, 0xD6876E4C, 0x3718A15F, 0xBD10596A, 0x5C8F9679, + 0x05A7DC98, 0xE438138B, 0x6E30EBBE, 0x8FAF24AD, 0xD320B2D4, 0x32BF7DC7, 0xB8B785F2, 0x59284AE1, + 0x0AE71199, 0xEB78DE8A, 0x617026BF, 0x80EFE9AC, 0xDC607FD5, 0x3DFFB0C6, 0xB7F748F3, 0x566887E0, + 0x0F40CD01, 0xEEDF0212, 0x64D7FA27, 0x85483534, 0xD9C7A34D, 0x38586C5E, 0xB250946B, 0x53CF5B78, + 0x1467229B, 0xF5F8ED88, 0x7FF015BD, 0x9E6FDAAE, 0xC2E04CD7, 0x237F83C4, 0xA9777BF1, 0x48E8B4E2, + 0x11C0FE03, 0xF05F3110, 0x7A57C925, 0x9BC80636, 0xC747904F, 0x26D85F5C, 0xACD0A769, 0x4D4F687A, + 0x1E803302, 0xFF1FFC11, 0x75170424, 0x9488CB37, 0xC8075D4E, 0x2998925D, 0xA3906A68, 0x420FA57B, + 0x1B27EF9A, 0xFAB82089, 0x70B0D8BC, 0x912F17AF, 0xCDA081D6, 0x2C3F4EC5, 0xA637B6F0, 0x47A879E3, + 0x28CE449F, 0xC9518B8C, 0x435973B9, 0xA2C6BCAA, 0xFE492AD3, 0x1FD6E5C0, 0x95DE1DF5, 0x7441D2E6, + 0x2D699807, 0xCCF65714, 0x46FEAF21, 0xA7616032, 0xFBEEF64B, 0x1A713958, 0x9079C16D, 0x71E60E7E, + 0x22295506, 0xC3B69A15, 0x49BE6220, 0xA821AD33, 0xF4AE3B4A, 0x1531F459, 0x9F390C6C, 0x7EA6C37F, + 0x278E899E, 0xC611468D, 0x4C19BEB8, 0xAD8671AB, 0xF109E7D2, 0x109628C1, 0x9A9ED0F4, 0x7B011FE7, + 0x3CA96604, 0xDD36A917, 0x573E5122, 0xB6A19E31, 0xEA2E0848, 0x0BB1C75B, 0x81B93F6E, 0x6026F07D, + 0x390EBA9C, 0xD891758F, 0x52998DBA, 0xB30642A9, 0xEF89D4D0, 0x0E161BC3, 0x841EE3F6, 0x65812CE5, + 0x364E779D, 0xD7D1B88E, 0x5DD940BB, 0xBC468FA8, 0xE0C919D1, 0x0156D6C2, 0x8B5E2EF7, 0x6AC1E1E4, + 0x33E9AB05, 0xD2766416, 0x587E9C23, 0xB9E15330, 0xE56EC549, 0x04F10A5A, 0x8EF9F26F, 0x6F663D7C, + 0x50358897, 0xB1AA4784, 0x3BA2BFB1, 0xDA3D70A2, 0x86B2E6DB, 0x672D29C8, 0xED25D1FD, 0x0CBA1EEE, + 0x5592540F, 0xB40D9B1C, 0x3E056329, 0xDF9AAC3A, 0x83153A43, 0x628AF550, 0xE8820D65, 0x091DC276, + 0x5AD2990E, 0xBB4D561D, 0x3145AE28, 0xD0DA613B, 0x8C55F742, 0x6DCA3851, 0xE7C2C064, 0x065D0F77, + 0x5F754596, 0xBEEA8A85, 0x34E272B0, 0xD57DBDA3, 0x89F22BDA, 0x686DE4C9, 0xE2651CFC, 0x03FAD3EF, + 0x4452AA0C, 0xA5CD651F, 0x2FC59D2A, 0xCE5A5239, 0x92D5C440, 0x734A0B53, 0xF942F366, 0x18DD3C75, + 0x41F57694, 0xA06AB987, 0x2A6241B2, 0xCBFD8EA1, 0x977218D8, 0x76EDD7CB, 0xFCE52FFE, 0x1D7AE0ED, + 0x4EB5BB95, 0xAF2A7486, 0x25228CB3, 0xC4BD43A0, 0x9832D5D9, 0x79AD1ACA, 0xF3A5E2FF, 0x123A2DEC, + 0x4B12670D, 0xAA8DA81E, 0x2085502B, 0xC11A9F38, 0x9D950941, 0x7C0AC652, 0xF6023E67, 0x179DF174, + 0x78FBCC08, 0x9964031B, 0x136CFB2E, 0xF2F3343D, 0xAE7CA244, 0x4FE36D57, 0xC5EB9562, 0x24745A71, + 0x7D5C1090, 0x9CC3DF83, 0x16CB27B6, 0xF754E8A5, 0xABDB7EDC, 0x4A44B1CF, 0xC04C49FA, 0x21D386E9, + 0x721CDD91, 0x93831282, 0x198BEAB7, 0xF81425A4, 0xA49BB3DD, 0x45047CCE, 0xCF0C84FB, 0x2E934BE8, + 0x77BB0109, 0x9624CE1A, 0x1C2C362F, 0xFDB3F93C, 0xA13C6F45, 0x40A3A056, 0xCAAB5863, 0x2B349770, + 0x6C9CEE93, 0x8D032180, 0x070BD9B5, 0xE69416A6, 0xBA1B80DF, 0x5B844FCC, 0xD18CB7F9, 0x301378EA, + 0x693B320B, 0x88A4FD18, 0x02AC052D, 0xE333CA3E, 0xBFBC5C47, 0x5E239354, 0xD42B6B61, 0x35B4A472, + 0x667BFF0A, 0x87E43019, 0x0DECC82C, 0xEC73073F, 0xB0FC9146, 0x51635E55, 0xDB6BA660, 0x3AF46973, + 0x63DC2392, 0x8243EC81, 0x084B14B4, 0xE9D4DBA7, 0xB55B4DDE, 0x54C482CD, 0xDECC7AF8, 0x3F53B5EB, +}; -static uint32_t _MULalpha(uint8_t c) +static uint32_t MULa(int c) { - return ( ( ((uint32_t)_MULxPOW(c,23, 0xa9)) << 24 ) | - ( ((uint32_t)_MULxPOW(c, 245, 0xa9)) << 16 ) | - ( ((uint32_t)_MULxPOW(c, 48, 0xa9)) << 8 ) | - ( ((uint32_t)_MULxPOW(c, 239, 0xa9)) ) ) ; + return mula[c]; } +static const uint32_t diva[256] = { + 0x00000000, 0x180F40CD, 0x301E8033, 0x2811C0FE, 0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998, + 0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32, 0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254, + 0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x01E19FCF, 0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9, + 0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403, 0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65, + 0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C, 0x32751704, 0x2A7A57C9, 0x026B9737, 0x1A64D7FA, + 0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550, 0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36, + 0x7BB9E153, 0x63B6A19E, 0x4BA76160, 0x53A821AD, 0x1B854835, 0x038A08F8, 0x2B9BC806, 0x339488CB, + 0xBBC11A9F, 0xA3CE5A52, 0x8BDF9AAC, 0x93D0DA61, 0xDBFDB3F9, 0xC3F2F334, 0xEBE333CA, 0xF3EC7307, + 0xA492D5C4, 0xBC9D9509, 0x948C55F7, 0x8C83153A, 0xC4AE7CA2, 0xDCA13C6F, 0xF4B0FC91, 0xECBFBC5C, + 0x64EA2E08, 0x7CE56EC5, 0x54F4AE3B, 0x4CFBEEF6, 0x04D6876E, 0x1CD9C7A3, 0x34C8075D, 0x2CC74790, + 0x8D628AF5, 0x956DCA38, 0xBD7C0AC6, 0xA5734A0B, 0xED5E2393, 0xF551635E, 0xDD40A3A0, 0xC54FE36D, + 0x4D1A7139, 0x551531F4, 0x7D04F10A, 0x650BB1C7, 0x2D26D85F, 0x35299892, 0x1D38586C, 0x053718A1, + 0xF6DB6BA6, 0xEED42B6B, 0xC6C5EB95, 0xDECAAB58, 0x96E7C2C0, 0x8EE8820D, 0xA6F942F3, 0xBEF6023E, + 0x36A3906A, 0x2EACD0A7, 0x06BD1059, 0x1EB25094, 0x569F390C, 0x4E9079C1, 0x6681B93F, 0x7E8EF9F2, + 0xDF2B3497, 0xC724745A, 0xEF35B4A4, 0xF73AF469, 0xBF179DF1, 0xA718DD3C, 0x8F091DC2, 0x97065D0F, + 0x1F53CF5B, 0x075C8F96, 0x2F4D4F68, 0x37420FA5, 0x7F6F663D, 0x676026F0, 0x4F71E60E, 0x577EA6C3, + 0xE18D0321, 0xF98243EC, 0xD1938312, 0xC99CC3DF, 0x81B1AA47, 0x99BEEA8A, 0xB1AF2A74, 0xA9A06AB9, + 0x21F5F8ED, 0x39FAB820, 0x11EB78DE, 0x09E43813, 0x41C9518B, 0x59C61146, 0x71D7D1B8, 0x69D89175, + 0xC87D5C10, 0xD0721CDD, 0xF863DC23, 0xE06C9CEE, 0xA841F576, 0xB04EB5BB, 0x985F7545, 0x80503588, + 0x0805A7DC, 0x100AE711, 0x381B27EF, 0x20146722, 0x68390EBA, 0x70364E77, 0x58278E89, 0x4028CE44, + 0xB3C4BD43, 0xABCBFD8E, 0x83DA3D70, 0x9BD57DBD, 0xD3F81425, 0xCBF754E8, 0xE3E69416, 0xFBE9D4DB, + 0x73BC468F, 0x6BB30642, 0x43A2C6BC, 0x5BAD8671, 0x1380EFE9, 0x0B8FAF24, 0x239E6FDA, 0x3B912F17, + 0x9A34E272, 0x823BA2BF, 0xAA2A6241, 0xB225228C, 0xFA084B14, 0xE2070BD9, 0xCA16CB27, 0xD2198BEA, + 0x5A4C19BE, 0x42435973, 0x6A52998D, 0x725DD940, 0x3A70B0D8, 0x227FF015, 0x0A6E30EB, 0x12617026, + 0x451FD6E5, 0x5D109628, 0x750156D6, 0x6D0E161B, 0x25237F83, 0x3D2C3F4E, 0x153DFFB0, 0x0D32BF7D, + 0x85672D29, 0x9D686DE4, 0xB579AD1A, 0xAD76EDD7, 0xE55B844F, 0xFD54C482, 0xD545047C, 0xCD4A44B1, + 0x6CEF89D4, 0x74E0C919, 0x5CF109E7, 0x44FE492A, 0x0CD320B2, 0x14DC607F, 0x3CCDA081, 0x24C2E04C, + 0xAC977218, 0xB49832D5, 0x9C89F22B, 0x8486B2E6, 0xCCABDB7E, 0xD4A49BB3, 0xFCB55B4D, 0xE4BA1B80, + 0x17566887, 0x0F59284A, 0x2748E8B4, 0x3F47A879, 0x776AC1E1, 0x6F65812C, 0x477441D2, 0x5F7B011F, + 0xD72E934B, 0xCF21D386, 0xE7301378, 0xFF3F53B5, 0xB7123A2D, 0xAF1D7AE0, 0x870CBA1E, 0x9F03FAD3, + 0x3EA637B6, 0x26A9777B, 0x0EB8B785, 0x16B7F748, 0x5E9A9ED0, 0x4695DE1D, 0x6E841EE3, 0x768B5E2E, + 0xFEDECC7A, 0xE6D18CB7, 0xCEC04C49, 0xD6CF0C84, 0x9EE2651C, 0x86ED25D1, 0xAEFCE52F, 0xB6F3A5E2, +}; -/* The function DIV alpha. -* Input c: 8-bit input. -* Output : 32-bit output. -* maps 8 bits to 32 bit. -*/ -static uint32_t _DIValpha(uint8_t c) +static uint32_t DIVa(int c) { - return ( ( ((uint32_t)_MULxPOW(c, 16, 0xa9)) << 24 ) | - ( ((uint32_t)_MULxPOW(c, 39, 0xa9)) << 16 ) | - ( ((uint32_t)_MULxPOW(c, 6, 0xa9)) << 8 ) | - ( ((uint32_t)_MULxPOW(c, 64, 0xa9)) ) ) ; + return diva[c]; } -/* The 32x32-bit S-Box S1 -* Input: a 32-bit input. -* Output: a 32-bit output of S1 box. -* The S-Box S1 maps a 32-bit input to a 32-bit output. -* w = w0 || w1 || w2 || w3 the 32-bit input with w0 the most and w3 the least significant byte. -* S1(w)= r0 || r1 || r2 || r3 with r0 the most and r3 the least significant byte. -*/ - -static uint32_t _S1(uint32_t w) +static void lfsr_init(snow3g_t *s, uint32_t f) { - uint8_t r0=0, r1=0, r2=0, r3=0; - uint8_t srw0 = SR[ (uint8_t)((w >> 24) & 0xff) ]; - uint8_t srw1 = SR[ (uint8_t)((w >> 16) & 0xff) ]; - uint8_t srw2 = SR[ (uint8_t)((w >> 8) & 0xff) ]; - uint8_t srw3 = SR[ (uint8_t)((w) & 0xff) ]; + uint8_t s0_0 = (s->s[0] >> 24) & 0xff; + uint8_t s0_1 = (s->s[0] >> 16) & 0xff; + uint8_t s0_2 = (s->s[0] >> 8) & 0xff; + uint8_t s0_3 = s->s[0] & 0xff; + uint8_t s11_0 = (s->s[11] >> 24) & 0xff; + uint8_t s11_1 = (s->s[11] >> 16) & 0xff; + uint8_t s11_2 = (s->s[11] >> 8) & 0xff; + uint8_t s11_3 = s->s[11] & 0xff; - r0 = ( ( _MULx( srw0 , 0x1b) ) ^ - ( srw1 ) ^ - ( srw2 ) ^ - ( (_MULx( srw3, 0x1b)) ^ srw3 ) - ); + uint32_t v0 = (s0_1 << 24) + | (s0_2 << 16) + | (s0_3 << 8); + uint32_t v11 = (s11_0 << 16) + | (s11_1 << 8) + | s11_2; + uint32_t v = v0 ^ MULa(s0_0) ^ s->s[2] ^ v11 ^ DIVa(s11_3) ^ f; - r1 = ( ( ( _MULx( srw0 , 0x1b) ) ^ srw0 ) ^ - ( _MULx(srw1, 0x1b) ) ^ - ( srw2 ) ^ - ( srw3 ) - ); +#if 0 + /* the specs do this */ + s->s[0] = s->s[1]; + s->s[1] = s->s[2]; + s->s[2] = s->s[3]; + s->s[3] = s->s[4]; + s->s[4] = s->s[5]; + s->s[5] = s->s[6]; + s->s[6] = s->s[7]; + s->s[7] = s->s[8]; + s->s[8] = s->s[9]; + s->s[9] = s->s[10]; + s->s[10] = s->s[11]; + s->s[11] = s->s[12]; + s->s[12] = s->s[13]; + s->s[13] = s->s[14]; + s->s[14] = s->s[15]; + s->s[15] = v; +#endif - r2 = ( ( srw0 ) ^ - ( ( _MULx( srw1 , 0x1b) ) ^ srw1 ) ^ - ( _MULx(srw2, 0x1b) ) ^ - ( srw3 ) - ); - - r3 = ( ( srw0 ) ^ - ( srw1 ) ^ - ( ( _MULx( srw2 , 0x1b) ) ^ srw2 ) ^ - ( _MULx( srw3, 0x1b) ) - ); - - return ( ( ((uint32_t)r0) << 24 ) | ( ((uint32_t)r1) << 16 ) | ( ((uint32_t)r2) << 8 ) | ( ((uint32_t)r3) ) ); + /* we do this, much less memory movement */ + s->s[0] = v; + s->s[16] = v; + s->s++; + if (s->s == &s->_s[16]) + s->s = &s->_s[0]; } -/* The 32x32-bit S-Box S2 -* Input: a 32-bit input. -* Output: a 32-bit output of S2 box. -* The S-Box S2 maps a 32-bit input to a 32-bit output. -* Let w = w0 || w1 || w2 || w3 the 32-bit input with w0 the most and w3 the least significant byte. -* Let S2(w)= r0 || r1 || r2 || r3 with r0 the most and r3 the least significant byte. -*/ - -static uint32_t _S2(uint32_t w) +static void lfsr_keystream(snow3g_t *s) { - uint8_t r0=0, r1=0, r2=0, r3=0; - uint8_t sqw0 = SQ[ (uint8_t)((w >> 24) & 0xff) ]; - uint8_t sqw1 = SQ[ (uint8_t)((w >> 16) & 0xff) ]; - uint8_t sqw2 = SQ[ (uint8_t)((w >> 8) & 0xff) ]; - uint8_t sqw3 = SQ[ (uint8_t)((w) & 0xff) ]; + uint8_t s0_0 = (s->s[0] >> 24) & 0xff; + uint8_t s0_1 = (s->s[0] >> 16) & 0xff; + uint8_t s0_2 = (s->s[0] >> 8) & 0xff; + uint8_t s0_3 = s->s[0] & 0xff; + uint8_t s11_0 = (s->s[11] >> 24) & 0xff; + uint8_t s11_1 = (s->s[11] >> 16) & 0xff; + uint8_t s11_2 = (s->s[11] >> 8) & 0xff; + uint8_t s11_3 = s->s[11] & 0xff; + uint32_t v0 = (s0_1 << 24) + | (s0_2 << 16) + | (s0_3 << 8); + uint32_t v11 = (s11_0 << 16) + | (s11_1 << 8) + | s11_2; + uint32_t v = v0 ^ MULa(s0_0) ^ s->s[2] ^ v11 ^ DIVa(s11_3); - r0 = ( ( _MULx( sqw0 , 0x69) ) ^ - ( sqw1 ) ^ - ( sqw2 ) ^ - ( (_MULx( sqw3, 0x69)) ^ sqw3 ) - ); +#if 0 + /* the specs do this */ + s->s[0] = s->s[1]; + s->s[1] = s->s[2]; + s->s[2] = s->s[3]; + s->s[3] = s->s[4]; + s->s[4] = s->s[5]; + s->s[5] = s->s[6]; + s->s[6] = s->s[7]; + s->s[7] = s->s[8]; + s->s[8] = s->s[9]; + s->s[9] = s->s[10]; + s->s[10] = s->s[11]; + s->s[11] = s->s[12]; + s->s[12] = s->s[13]; + s->s[13] = s->s[14]; + s->s[14] = s->s[15]; + s->s[15] = v; +#endif - r1 = ( ( ( _MULx( sqw0 , 0x69) ) ^ sqw0 ) ^ - ( _MULx(sqw1, 0x69) ) ^ - ( sqw2 ) ^ - ( sqw3 ) - ); - - r2 = ( ( sqw0 ) ^ - ( ( _MULx( sqw1 , 0x69) ) ^ sqw1 ) ^ - ( _MULx(sqw2, 0x69) ) ^ - ( sqw3 ) - ); - - r3 = ( ( sqw0 ) ^ - ( sqw1 ) ^ - ( ( _MULx( sqw2 , 0x69) ) ^ sqw2 ) ^ - ( _MULx( sqw3, 0x69) ) - ); - - return ( ( ((uint32_t)r0) << 24 ) | ( ((uint32_t)r1) << 16 ) | ( ((uint32_t)r2) << 8 ) | ( ((uint32_t)r3) ) ); + /* we do this, much less memory movement */ + s->s[0] = v; + s->s[16] = v; + s->s++; + if (s->s == &s->_s[16]) + s->s = &s->_s[0]; } -/* Clocking LFSR in initialization mode. -* LFSR Registers S0 to S15 are updated as the LFSR receives a single clock. -* Input F: a 32-bit word comes from output of FSM. -* See section 3.4.4. -*/ - -static void _snow3g_clock_LFSR_initialization_mode(uint32_t F, snow_3g_context_t *s3g_ctx_pP) +static uint32_t clock_fsm(snow3g_t *s) { - uint32_t v = ( ( (s3g_ctx_pP->LFSR_S0 << 8) & 0xffffff00 ) ^ - ( _MULalpha( (uint8_t)((s3g_ctx_pP->LFSR_S0>>24) & 0xff) ) ) ^ - ( s3g_ctx_pP->LFSR_S2 ) ^ - ( (s3g_ctx_pP->LFSR_S11 >> 8) & 0x00ffffff ) ^ - ( _DIValpha( (uint8_t)( ( s3g_ctx_pP->LFSR_S11) & 0xff ) ) ) ^ - ( F ) - ); + uint32_t f = (s->s[15] + s->r1) ^ s->r2; - s3g_ctx_pP->LFSR_S0 = s3g_ctx_pP->LFSR_S1; - s3g_ctx_pP->LFSR_S1 = s3g_ctx_pP->LFSR_S2; - s3g_ctx_pP->LFSR_S2 = s3g_ctx_pP->LFSR_S3; - s3g_ctx_pP->LFSR_S3 = s3g_ctx_pP->LFSR_S4; - s3g_ctx_pP->LFSR_S4 = s3g_ctx_pP->LFSR_S5; - s3g_ctx_pP->LFSR_S5 = s3g_ctx_pP->LFSR_S6; - s3g_ctx_pP->LFSR_S6 = s3g_ctx_pP->LFSR_S7; - s3g_ctx_pP->LFSR_S7 = s3g_ctx_pP->LFSR_S8; - s3g_ctx_pP->LFSR_S8 = s3g_ctx_pP->LFSR_S9; - s3g_ctx_pP->LFSR_S9 = s3g_ctx_pP->LFSR_S10; - s3g_ctx_pP->LFSR_S10 = s3g_ctx_pP->LFSR_S11; - s3g_ctx_pP->LFSR_S11 = s3g_ctx_pP->LFSR_S12; - s3g_ctx_pP->LFSR_S12 = s3g_ctx_pP->LFSR_S13; - s3g_ctx_pP->LFSR_S13 = s3g_ctx_pP->LFSR_S14; - s3g_ctx_pP->LFSR_S14 = s3g_ctx_pP->LFSR_S15; - s3g_ctx_pP->LFSR_S15 = v; + uint32_t r = s->r2 + (s->r3 ^ s->s[5]); + s->r3 = s2(s->r2); + s->r2 = s1(s->r1); + s->r1 = r; + + return f; } -/* Clocking LFSR in keystream mode. -* LFSR Registers S0 to S15 are updated as the LFSR receives a single clock. -* See section 3.4.5. -*/ -static void _snow3g_clock_LFSR_key_stream_mode(snow_3g_context_t *snow_3g_context_pP) +static uint32_t GET32(uint8_t *b) { - - uint32_t v = ( ( (snow_3g_context_pP->LFSR_S0 << 8) & 0xffffff00 ) ^ - ( _MULalpha( (uint8_t)((snow_3g_context_pP->LFSR_S0>>24) & 0xff) ) ) ^ - ( snow_3g_context_pP->LFSR_S2 ) ^ - ( (snow_3g_context_pP->LFSR_S11 >> 8) & 0x00ffffff ) ^ - ( _DIValpha( (uint8_t)( ( snow_3g_context_pP->LFSR_S11) & 0xff ) ) ) - ); - - snow_3g_context_pP->LFSR_S0 = snow_3g_context_pP->LFSR_S1; - snow_3g_context_pP->LFSR_S1 = snow_3g_context_pP->LFSR_S2; - snow_3g_context_pP->LFSR_S2 = snow_3g_context_pP->LFSR_S3; - snow_3g_context_pP->LFSR_S3 = snow_3g_context_pP->LFSR_S4; - snow_3g_context_pP->LFSR_S4 = snow_3g_context_pP->LFSR_S5; - snow_3g_context_pP->LFSR_S5 = snow_3g_context_pP->LFSR_S6; - snow_3g_context_pP->LFSR_S6 = snow_3g_context_pP->LFSR_S7; - snow_3g_context_pP->LFSR_S7 = snow_3g_context_pP->LFSR_S8; - snow_3g_context_pP->LFSR_S8 = snow_3g_context_pP->LFSR_S9; - snow_3g_context_pP->LFSR_S9 = snow_3g_context_pP->LFSR_S10; - snow_3g_context_pP->LFSR_S10 = snow_3g_context_pP->LFSR_S11; - snow_3g_context_pP->LFSR_S11 = snow_3g_context_pP->LFSR_S12; - snow_3g_context_pP->LFSR_S12 = snow_3g_context_pP->LFSR_S13; - snow_3g_context_pP->LFSR_S13 = snow_3g_context_pP->LFSR_S14; - snow_3g_context_pP->LFSR_S14 = snow_3g_context_pP->LFSR_S15; - snow_3g_context_pP->LFSR_S15 = v; + return ((uint32_t)b[0] << 24) + | ((uint32_t)b[1] << 16) + | ((uint32_t)b[2] << 8) + | (uint32_t)b[3]; } -/* Clocking FSM. -* Produces a 32-bit word F. -* Updates FSM registers R1, R2, R3. -* See Section 3.4.6. -*/ - -static uint32_t _snow3g_clock_fsm(snow_3g_context_t *snow_3g_context_pP) +static void snow3g_init(snow3g_t *s, uint8_t *_k, uint8_t *_iv) { - uint32_t F = ( ( snow_3g_context_pP->LFSR_S15 + snow_3g_context_pP->FSM_R1 ) & 0xffffffff ) ^ snow_3g_context_pP->FSM_R2 ; - uint32_t r = ( snow_3g_context_pP->FSM_R2 + ( snow_3g_context_pP->FSM_R3 ^ snow_3g_context_pP->LFSR_S5 ) ) & 0xffffffff ; + uint32_t k[4]; + uint32_t iv[4]; + for (int i = 0; i < 4; i++) k[i] = GET32(_k + i * 4); + for (int i = 0; i < 4; i++) iv[i] = GET32(_iv + i * 4); - snow_3g_context_pP->FSM_R3 = _S2(snow_3g_context_pP->FSM_R2); - snow_3g_context_pP->FSM_R2 = _S1(snow_3g_context_pP->FSM_R1); - snow_3g_context_pP->FSM_R1 = r; + s->s = &s->_s[0]; - return F; -} + s->s[15] = k[3] ^ iv[0]; + s->s[14] = k[2]; + s->s[13] = k[1]; + s->s[12] = k[0] ^ iv[1]; + s->s[11] = k[3] ^ 0xffffffff; + s->s[10] = k[2] ^ 0xffffffff ^ iv[2]; + s->s[9] = k[1] ^ 0xffffffff ^ iv[3]; + s->s[8] = k[0] ^ 0xffffffff; + s->s[7] = k[3]; + s->s[6] = k[2]; + s->s[5] = k[1]; + s->s[4] = k[0]; + s->s[3] = k[3] ^ 0xffffffff; + s->s[2] = k[2] ^ 0xffffffff; + s->s[1] = k[1] ^ 0xffffffff; + s->s[0] = k[0] ^ 0xffffffff; + s->r1 = s->r2 = s->r3 = 0; -/* Initialization. - * Input k[4]: Four 32-bit words making up 128-bit key. - * Input IV[4]: Four 32-bit words making 128-bit initialization variable. - * Output: All the LFSRs and FSM are initialized for key generation. - * See Section 4.1. - */ - -void snow3g_initialize(uint32_t k[4], uint32_t IV[4], snow_3g_context_t *snow_3g_context_pP) -{ - - uint8_t i = 0; - uint32_t F = 0x0; - - snow_3g_context_pP->LFSR_S15 = k[3] ^ IV[0]; - snow_3g_context_pP->LFSR_S14 = k[2]; - snow_3g_context_pP->LFSR_S13 = k[1]; - snow_3g_context_pP->LFSR_S12 = k[0] ^ IV[1]; - - snow_3g_context_pP->LFSR_S11 = k[3] ^ 0xffffffff; - snow_3g_context_pP->LFSR_S10 = k[2] ^ 0xffffffff ^ IV[2]; - snow_3g_context_pP->LFSR_S9 = k[1] ^ 0xffffffff ^ IV[3]; - snow_3g_context_pP->LFSR_S8 = k[0] ^ 0xffffffff; - - snow_3g_context_pP->LFSR_S7 = k[3]; - snow_3g_context_pP->LFSR_S6 = k[2]; - snow_3g_context_pP->LFSR_S5 = k[1]; - snow_3g_context_pP->LFSR_S4 = k[0]; - - snow_3g_context_pP->LFSR_S3 = k[3] ^ 0xffffffff; - snow_3g_context_pP->LFSR_S2 = k[2] ^ 0xffffffff; - snow_3g_context_pP->LFSR_S1 = k[1] ^ 0xffffffff; - snow_3g_context_pP->LFSR_S0 = k[0] ^ 0xffffffff; - - snow_3g_context_pP->FSM_R1 = 0x0; - snow_3g_context_pP->FSM_R2 = 0x0; - snow_3g_context_pP->FSM_R3 = 0x0; - - for(i=0; i<32; i++) { - F = _snow3g_clock_fsm(snow_3g_context_pP); - _snow3g_clock_LFSR_initialization_mode(F, snow_3g_context_pP); + for (int i = 0; i < 32; i++) { + uint32_t f = clock_fsm(s); + lfsr_init(s, f); } + /* start keystream generation (this is beginning of spec 4.2) */ + clock_fsm(s); + lfsr_keystream(s); } -/* Generation of Keystream. -* input n: number of 32-bit words of keystream. -* input z: space for the generated keystream, assumes -* memory is allocated already. -* output: generated keystream which is filled in z -* See section 4.2. -*/ - -void snow3g_generate_key_stream(uint32_t n, uint32_t *ks, snow_3g_context_t *snow_3g_context_pP) +static uint32_t generate_keystream_step(snow3g_t *s) { - uint32_t t = 0; - uint32_t F = 0x0; - - _snow3g_clock_fsm(snow_3g_context_pP); /* Clock FSM once. Discard the output. */ - _snow3g_clock_LFSR_key_stream_mode(snow_3g_context_pP); /* Clock LFSR in keystream mode once. */ - - for ( t=0; tLFSR_S0; /* STEP 2 */ - - /* Note that ks[t] corresponds to z_{t+1} in section 4.2*/ - - _snow3g_clock_LFSR_key_stream_mode(snow_3g_context_pP); /* STEP 3 */ - } + uint32_t f = clock_fsm(s); + uint32_t ret = f ^ s->s[0]; + lfsr_keystream(s); + return ret; } +void snow3g_ciphering(uint32_t count, int bearer, int direction, const uint8_t *key, int length, const uint8_t *in, uint8_t *out) +{ + snow3g_t s; + + uint8_t k[16]; + k[0] = key[12]; + k[1] = key[13]; + k[2] = key[14]; + k[3] = key[15]; + k[4] = key[8]; + k[5] = key[9]; + k[6] = key[10]; + k[7] = key[11]; + k[8] = key[4]; + k[9] = key[5]; + k[10] = key[6]; + k[11] = key[7]; + k[12] = key[0]; + k[13] = key[1]; + k[14] = key[2]; + k[15] = key[3]; + + uint8_t iv[16] = {0}; + iv[4] = (count >> 24) & 0xff; + iv[5] = (count >> 16) & 0xff; + iv[6] = (count >> 8) & 0xff; + iv[7] = count & 0xff; + + iv[0] = (bearer << 3) | (direction << 2); + + iv[12] = (count >> 24) & 0xff; + iv[13] = (count >> 16) & 0xff; + iv[14] = (count >> 8) & 0xff; + iv[15] = count & 0xff; + + iv[8] = (bearer << 3) | (direction << 2); + + snow3g_init(&s, k, iv); + + int keystream_count = ((unsigned)length + 3) / 4; + uint32_t _keystream[keystream_count]; + + for (int i = 0; i < keystream_count; i++) + _keystream[i] = htonl(generate_keystream_step(&s)); + + uint8_t *keystream = (uint8_t *)_keystream; + for (int i = 0; i < length; i++) + out[i] = in[i] ^ keystream[i]; +} + +static int MIN(int a, int b) +{ + if (a < b) return a; + return b; +} + +static inline uint64_t GET64(const uint8_t *p, int available_bytes) +{ + uint64_t a = 0; + uint64_t b = 0; + uint64_t c = 0; + uint64_t d = 0; + uint64_t e = 0; + uint64_t f = 0; + uint64_t g = 0; + uint64_t h = 0; + switch (available_bytes) { + case 8: h = p[7]; /* falltrough */ + case 7: g = p[6]; /* falltrough */ + case 6: f = p[5]; /* falltrough */ + case 5: e = p[4]; /* falltrough */ + case 4: d = p[3]; /* falltrough */ + case 3: c = p[2]; /* falltrough */ + case 2: b = p[1]; /* falltrough */ + case 1: a = p[0]; + } + + return (a << (32+24)) | (b << (32+16)) | (c << (32+8)) | (d << 32) + | (e << 24) | (f << 16) | (g << 8) | h; +} + +static uint64_t MULx64(uint64_t v, uint64_t c) +{ + if (v & ((uint64_t)1 << 63)) + return (v << 1) ^ c; + return v << 1; +} + +static uint64_t MULxPOW64(uint64_t v, int i, uint64_t c) +{ + if (i == 0) return v; + return MULx64(MULxPOW64(v, i-1, c), c); +} + +static uint64_t MUL64(uint64_t v, uint64_t p, uint64_t c) +{ + uint64_t result = 0; + for (int i = 0; i < 64; i++) { + if ((p >> i) & 1) + result ^= MULxPOW64(v, i, c); + } + return result; +} + +static inline uint64_t mul_p(const uint64_t pm[7][256], uint64_t x) +{ + uint64_t x0 = (x >> (32 + 24)) & 255; + uint64_t x1 = (x >> (32 + 16)) & 255; + uint64_t x2 = (x >> (32 + 8)) & 255; + uint64_t x3 = (x >> 32) & 255; + uint64_t x4 = (x >> 24) & 255; + uint64_t x5 = (x >> 16) & 255; + uint64_t x6 = (x >> 8) & 255; + uint64_t x7 = x & 255; + return pm[0][x7] ^ + pm[1][x6] ^ + pm[2][x5] ^ + pm[3][x4] ^ + pm[4][x3] ^ + pm[5][x2] ^ + pm[6][x1] ^ + pm[7][x0]; +} + +static void _snow3g_integrity(uint32_t count, uint32_t fresh, int direction, const uint8_t *key, int length, const uint8_t *in, uint8_t *out) +{ + snow3g_t s; + + uint8_t k[16]; + k[0] = key[12]; + k[1] = key[13]; + k[2] = key[14]; + k[3] = key[15]; + k[4] = key[8]; + k[5] = key[9]; + k[6] = key[10]; + k[7] = key[11]; + k[8] = key[4]; + k[9] = key[5]; + k[10] = key[6]; + k[11] = key[7]; + k[12] = key[0]; + k[13] = key[1]; + k[14] = key[2]; + k[15] = key[3]; + + uint8_t iv[16] = {0}; + iv[4] = ((count >> 24) & 0xff) ^ ((direction & 1) << 7); + iv[5] = (count >> 16) & 0xff; + iv[6] = (count >> 8) & 0xff; + iv[7] = count & 0xff; + + iv[0] = (fresh >> 24) & 0xff; + iv[1] = (fresh >> 16) & 0xff; + iv[2] = ((fresh >> 8) & 0xff) ^ ((direction & 1) << 7); + iv[3] = fresh & 0xff; + + iv[12] = (count >> 24) & 0xff; + iv[13] = (count >> 16) & 0xff; + iv[14] = (count >> 8) & 0xff; + iv[15] = count & 0xff; + + iv[8] = (fresh >> 24) & 0xff; + iv[9] = (fresh >> 16) & 0xff; + iv[10] = (fresh >> 8) & 0xff; + iv[11] = fresh & 0xff; + + snow3g_init(&s, k, iv); + + uint32_t z[5]; + for (int i = 0; i < 5; i++) + z[i] = generate_keystream_step(&s); + + int d = (length * 8 + 63) / 64 + 1; + uint64_t p = ((uint64_t)z[0] << 32) | z[1]; + uint64_t q = ((uint64_t)z[2] << 32) | z[3]; + uint32_t otp = z[4]; + + uint64_t eval = 0; + + /* precomputation table */ + uint64_t pm[8][256]; + pm[0][0] = pm[1][0] = pm[2][0] = pm[3][0] = pm[4][0] = pm[5][0] = pm[6][0] = pm[7][0] = 0; + pm[0][1] = p; + + for (int i = 1; i <= 63; i++) { + pm[i >> 3][1 << (i & 0x07)] = pm[(i - 1) >> 3][1 << ((i - 1) & 0x07)] << 1; + if (pm[(i - 1) >> 3][1 << ((i - 1) & 0x07)] & 0x8000000000000000ULL) + pm[i >> 3][1 << (i & 0x07)] = pm[i >> 3][1 << (i & 0x07)] ^ 0x1b; + } + + for (int i = 0; i <= 7; i++) { + for (int j = 1; j <= 7; j++) { + for (int k = 1; k <= (1 << j) - 1; k++) { + pm[i][(1 << j) + k] = pm[i][1 << j] ^ pm[i][k]; + } + } + } + + for (int i = 0; i <= d - 3; i++) { + uint64_t m = GET64(in + i * 8, 8); + eval = mul_p(pm, eval ^ m); + } + uint64_t m = GET64(in + (d - 2) * 8, MIN(8, length - (d - 2) * 8)); + eval = mul_p(pm, eval ^ m); + + eval ^= (uint64_t)length * 8; + eval = MUL64(eval, q, 0x1b); + eval >>= 32; + eval ^= otp; + + out[0] = (eval >> 24) & 0xff; + out[1] = (eval >> 16) & 0xff; + out[2] = (eval >> 8) & 0xff; + out[3] = eval & 0xff; +} + +void snow3g_integrity(uint32_t count, int bearer, int direction, const uint8_t *key, int length, const uint8_t *in, uint8_t *out) +{ + _snow3g_integrity(count, (uint32_t)bearer << 27, direction, key, length, in, out); +} + +#ifndef NO_MAIN + +#include +#include +#include + +int main(void) +{ + if (1) { + /* 4.3 test set 1 */ + uint32_t count = 0x72A4F20F; + int bearer = 0x0c; + int direction = 1; + uint8_t k[16] = { 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48 }; + uint8_t data[] = { + 0x7E, 0xC6, 0x12, 0x72, 0x74, 0x3B, 0xF1, 0x61, 0x47, 0x26, 0x44, 0x6A, 0x6C, 0x38, 0xCE, 0xD1, + 0x66, 0xF6, 0xCA, 0x76, 0xEB, 0x54, 0x30, 0x04, 0x42, 0x86, 0x34, 0x6C, 0xEF, 0x13, 0x0F, 0x92, + 0x92, 0x2B, 0x03, 0x45, 0x0D, 0x3A, 0x99, 0x75, 0xE5, 0xBD, 0x2E, 0xA0, 0xEB, 0x55, 0xAD, 0x8E, + 0x1B, 0x19, 0x9E, 0x3E, 0xC4, 0x31, 0x60, 0x20, 0xE9, 0xA1, 0xB2, 0x85, 0xE7, 0x62, 0x79, 0x53, + 0x59, 0xB7, 0xBD, 0xFD, 0x39, 0xBE, 0xF4, 0xB2, 0x48, 0x45, 0x83, 0xD5, 0xAF, 0xE0, 0x82, 0xAE, + 0xE6, 0x38, 0xBF, 0x5F, 0xD5, 0xA6, 0x06, 0x19, 0x39, 0x01, 0xA0, 0x8F, 0x4A, 0xB4, 0x1A, 0xAB, + 0x9B, 0x13, 0x48, 0x80 + }; + snow3g_ciphering(count, bearer, direction, k, 798/8, data, data); + printf("ciphered:"); + for (int i = 0; i < 798/8; i++) printf(" %2.2x", data[i]); + printf("\n"); + } + + if (1) { + /* 5.3 test set 4 */ + uint32_t count = 0x14793E41; + uint32_t fresh = 0x0397E8FD; + int direction = 1; + uint8_t k[16] = { 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9, 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E }; + uint8_t data[] = { + 0xD0, 0xA7, 0xD4, 0x63, 0xDF, 0x9F, 0xB2, 0xB2, 0x78, 0x83, 0x3F, 0xA0, 0x2E, 0x23, 0x5A, 0xA1, + 0x72, 0xBD, 0x97, 0x0C, 0x14, 0x73, 0xE1, 0x29, 0x07, 0xFB, 0x64, 0x8B, 0x65, 0x99, 0xAA, 0xA0, + 0xB2, 0x4A, 0x03, 0x86, 0x65, 0x42, 0x2B, 0x20, 0xA4, 0x99, 0x27, 0x6A, 0x50, 0x42, 0x70, 0x09 + }; + uint8_t mac[4]; + _snow3g_integrity(count, fresh, direction, k, 384/8, data, mac); + printf("mac: %2.2x %2.2x %2.2x %2.2x\n", mac[0], mac[1], mac[2], mac[3]); + } + + if (1) { + /* speed test */ + uint8_t data[1500]; + /* keys copied from above */ + uint8_t k[16] = { 0xC7, 0x36, 0xC6, 0xAA, 0xB2, 0x2B, 0xFF, 0xF9, 0x1E, 0x26, 0x98, 0xD2, 0xE2, 0x2A, 0xD5, 0x7E }; + uint8_t k2[16] = { 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48 }; + int count = 100 * 1000 * 10; + struct timespec start, end; + for (int i = 0; i < 1500; i++) data[i] = i; + if (clock_gettime(CLOCK_REALTIME, &start) == -1) abort(); + for (int i = 0; i < count; i++) { + uint8_t out[1500]; + uint8_t mac[4]; + snow3g_ciphering(i /* count */, 1, 1, k, 1500, data, out); + snow3g_integrity(i /* count */, 1, 1, k2, 1500, out, mac); + } + clock_gettime(CLOCK_REALTIME, &end); + uint64_t t1 = (uint64_t)start.tv_sec * 1000 + start.tv_nsec / 1000000; + uint64_t t2 = (uint64_t)end.tv_sec * 1000 + end.tv_nsec / 1000000; + printf("throughput = %g Mb/s time %g\n", ((uint64_t)count * 8. * 1500 / ((t2 - t1)/1000.)) / 1000000., (t2 - t1) / 1000.); + } + + return 0; +} + +#endif /* !NO_MAIN */ diff --git a/openair3/SECU/snow3g.h b/openair3/SECU/snow3g.h index fcad5e9f8d..3342e36d04 100644 --- a/openair3/SECU/snow3g.h +++ b/openair3/SECU/snow3g.h @@ -19,59 +19,24 @@ * contact@openairinterface.org */ -/*! \file snow3g.h -* \brief -* \author Open source Adapted from Specification of the 3GPP Confidentiality and -* Integrity Algorithms UEA2 & UIA2. Document 2: SNOW 3G Specification -* \integrators Kharbach Othmane, GAUTHIER Lionel. -* \date 2014 -* \version -* \note -* \bug -* \warning -*/ -#ifndef SNOW3G_H_ -#define SNOW3G_H_ +#ifndef _SNOW3G_H_ +#define _SNOW3G_H_ -typedef struct snow_3g_context_s { - uint32_t LFSR_S0; - uint32_t LFSR_S1; - uint32_t LFSR_S2; - uint32_t LFSR_S3; - uint32_t LFSR_S4; - uint32_t LFSR_S5; - uint32_t LFSR_S6; - uint32_t LFSR_S7; - uint32_t LFSR_S8; - uint32_t LFSR_S9; - uint32_t LFSR_S10; - uint32_t LFSR_S11; - uint32_t LFSR_S12; - uint32_t LFSR_S13; - uint32_t LFSR_S14; - uint32_t LFSR_S15; +#include - /* FSM : The Finite State Machine has three 32-bit registers R1, R2 and R3. - */ - uint32_t FSM_R1; - uint32_t FSM_R2; - uint32_t FSM_R3; -} snow_3g_context_t; +void snow3g_ciphering(uint32_t count, + int bearer, + int direction, + const uint8_t *key, + int length, + const uint8_t *in, + uint8_t *out); +void snow3g_integrity(uint32_t count, + int bearer, + int direction, + const uint8_t *key, + int length, + const uint8_t *in, + uint8_t *out); -/* Initialization. -* Input k[4]: Four 32-bit words making up 128-bit key. -* Input IV[4]: Four 32-bit words making 128-bit initialization variable. -* Output: All the LFSRs and FSM are initialized for key generation. -*/ -void snow3g_initialize(uint32_t k[4], uint32_t IV[4], snow_3g_context_t *snow_3g_context_pP); - -/* Generation of Keystream. -* input n: number of 32-bit words of keystream. -* input z: space for the generated keystream, assumes -* memory is allocated already. -* output: generated keystream which is filled in z -*/ - -void snow3g_generate_key_stream(uint32_t n, uint32_t *z, snow_3g_context_t *snow_3g_context_pP); - -#endif +#endif /* _SNOW3G_H_ */ From 2eff246d646669b6889945a036ce25cbc6128c2a Mon Sep 17 00:00:00 2001 From: Jaroslava Fiedlerova Date: Mon, 8 Jul 2024 11:52:04 +0200 Subject: [PATCH 3/5] ci: modification of SA-2x2, 60 MHz TDD testcase conf to use nea1/nia1 --- .../conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf b/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf index fc3a264c2b..2e37ce393b 100644 --- a/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf +++ b/ci-scripts/conf_files/gnb.sa.band77.162prb.usrpn310.2x2.conf @@ -226,17 +226,17 @@ security = { # preferred ciphering algorithms # the first one of the list that an UE supports in chosen # valid values: nea0, nea1, nea2, nea3 - ciphering_algorithms = ( "nea0" ); + ciphering_algorithms = ( "nea1", "nea0" ); # preferred integrity algorithms # the first one of the list that an UE supports in chosen # valid values: nia0, nia1, nia2, nia3 - integrity_algorithms = ( "nia2", "nia0" ); + integrity_algorithms = ( "nia1", "nia0" ); # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' drb_ciphering = "yes"; - drb_integrity = "no"; + drb_integrity = "yes"; }; log_config : From 523d84634ac2b2e19dd997f34cae05e725f5ea14 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Wed, 11 Sep 2024 15:57:13 +0200 Subject: [PATCH 4/5] snow3g: add a test program To use: cd mkdir build cd build cmake .. -GNinja -DENABLE_TESTS=ON ninja tests (alternatively: ninja snow3g_tests) ctest (alternatively: ctest -R snow3g_tests) --- openair2/LAYER2/CMakeLists.txt | 22 + openair2/LAYER2/nr_pdcp/CMakeLists.txt | 28 + openair2/LAYER2/nr_pdcp/tests/CMakeLists.txt | 26 + openair2/LAYER2/nr_pdcp/tests/snow3g_tests.c | 641 +++++++++++++++++++ 4 files changed, 717 insertions(+) create mode 100644 openair2/LAYER2/nr_pdcp/CMakeLists.txt create mode 100644 openair2/LAYER2/nr_pdcp/tests/CMakeLists.txt create mode 100644 openair2/LAYER2/nr_pdcp/tests/snow3g_tests.c diff --git a/openair2/LAYER2/CMakeLists.txt b/openair2/LAYER2/CMakeLists.txt index 9360ed7b2b..dc084a89e0 100644 --- a/openair2/LAYER2/CMakeLists.txt +++ b/openair2/LAYER2/CMakeLists.txt @@ -1,2 +1,24 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ + add_subdirectory(nr_rlc) +add_subdirectory(nr_pdcp) add_subdirectory(NR_MAC_UE) diff --git a/openair2/LAYER2/nr_pdcp/CMakeLists.txt b/openair2/LAYER2/nr_pdcp/CMakeLists.txt new file mode 100644 index 0000000000..8b96f10ebe --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/CMakeLists.txt @@ -0,0 +1,28 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ + +add_library(nr_pdcp_snow3g OBJECT + nr_pdcp_integrity_nia1.c + nr_pdcp_security_nea1.c) + +if (ENABLE_TESTS) + add_subdirectory(tests) +endif () diff --git a/openair2/LAYER2/nr_pdcp/tests/CMakeLists.txt b/openair2/LAYER2/nr_pdcp/tests/CMakeLists.txt new file mode 100644 index 0000000000..1c69906b03 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/tests/CMakeLists.txt @@ -0,0 +1,26 @@ +#/* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ + +add_executable(snow3g_tests snow3g_tests.c) +target_link_libraries(snow3g_tests PRIVATE nr_pdcp_snow3g minimal_lib SECURITY) +add_test(NAME snow3g_tests + COMMAND snow3g_tests) +add_dependencies(tests snow3g_tests) diff --git a/openair2/LAYER2/nr_pdcp/tests/snow3g_tests.c b/openair2/LAYER2/nr_pdcp/tests/snow3g_tests.c new file mode 100644 index 0000000000..54adb02576 --- /dev/null +++ b/openair2/LAYER2/nr_pdcp/tests/snow3g_tests.c @@ -0,0 +1,641 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include + +/* dirty include, needed because calling _snow3g_integrity() is the only + * way to test integrity (the spec uses 'fresh' directly and snow3g_integrity() + * or nr_pdcp_integrity_nia1_integrity() use 'bearer' to derive 'fresh') and + * the function _snow3g_integrity() is static + */ +#include "openair3/SECU/snow3g.c" + +#include "nr_pdcp/nr_pdcp_security_nea1.h" +#include "common/utils/assertions.h" +#include "common/utils/LOG/log.h" + +/* tests are from "Specification of the 3GPP Confidentiality and Integrity + * Algorithms UEA2&UIA2 - Document 4: Design Conformance Test Data" + * + * See also 33.501: + * + * D.4.2 128-NEA1 + * For 128-NEA1 is the test data for UEA2 in TS 35.217 [36] can be reused + * directly as there is an exact, one-to-one mapping between UEA2 inputs + * and 128-NEA1 inputs. + * D.4.3 128-NIA1 + * For 128-NIA1 is the test data for 128-EIA1 in clause C.4 of TS 33.401 + * [10] can be reused directly as there is an exact, one-to-one mapping + * between 128-EIA1 inputs and 128-NIA1 inputs. + */ + +/* transform a length in bits to a length in bytes - may introduce padding bits */ +#define BITS2BYTES(x) (((x)+7) / 8) + +/* transform an ASCII hexadecimal character into its binary form */ +static int hex(int v) +{ + if (v >= '0' && v <= '9') return v - '0'; + if (v >= 'a' && v <= 'f') return v + 10 - 'a'; + return v + 10 - 'A'; +} + +/* transform an ASCII hexadecimal string (with optional spaces) + * into its binary form + */ +static unsigned char *s2b(char *s) +{ + unsigned char *out = malloc(strlen(s) * 2); + unsigned char *to = out; + DevAssert(out != NULL); + + while (*s) { + if (*s == ' ') { s++; continue; } + int a = hex(*s++); + int b = hex(*s++); + *to++ = (a << 4) | b; + } + + return out; +} + +static void print_buffer(unsigned char *buffer, int length, char *name) +{ + printf("%s[%d] ", name, length); + for (int i = 0; i < length; i++) + printf(" %2.2x", buffer[i]); + printf("\n"); +} + +/* ciphering tests */ + +typedef struct { + char *name; + char *key; + char *plaintext; + char *ciphertext; + uint32_t count; + int bearer; + int direction; + int length_in_bits; +} uea2_test_data_t; + +static int test_uea2(uea2_test_data_t *test) +{ + unsigned char *plaintext = s2b(test->plaintext); + unsigned char *ciphertext = s2b(test->ciphertext); + unsigned char *key = s2b(test->key); + int count = test->count; + int bearer = test->bearer + 1; /* nr_pdcp_security_nea1_cipher does -1 */ + int direction = test->direction; + int length = BITS2BYTES(test->length_in_bits); + + printf("%s\n", test->name); + + print_buffer(key, 16, "KEY "); + print_buffer(plaintext, length, "PLAIN "); + + stream_security_context_t *ctx = nr_pdcp_security_nea1_init(key); + DevAssert(ctx != NULL); + + nr_pdcp_security_nea1_cipher(ctx, plaintext, length, bearer, count, direction); + /* clear unused bits */ + int unused_bits = length * 8 - test->length_in_bits; + plaintext[length - 1] &= 0xff << unused_bits; + + nr_pdcp_security_nea1_free_security(ctx); + + int ret = memcmp(ciphertext, plaintext, length) != 0; + + printf("COMPUTED[%d] ", length); for (int i = 0; i < length; i++) printf(" %2.2x", plaintext[i]); printf("\n"); + printf("EXPECTED[%d] ", length); for (int i = 0; i < length; i++) printf(" %2.2x", ciphertext[i]); printf("\n"); + free(key); + free(plaintext); + free(ciphertext); + + printf("%s\n", ret ? "FAIL" : "OK"); + + return ret; +} + +static int uea2_test_set_1(void) +{ + uea2_test_data_t test = { + .name = "UEA2 test set 1", + .key = "D3C5D592327FB11C4035C6680AF8C6D1", + .plaintext = "981BA682 4C1BFB1A B4854720 29B71D80" + "8CE33E2C C3C0B5FC 1F3DE8A6 DC66B1F0", + .ciphertext = "5D5BFE75 EB04F68C E0A12377 EA00B37D" + "47C6A0BA 06309155 086A859C 4341B378", + .count = 0x398A59B4, + .bearer = 0x15, + .direction = 1, + .length_in_bits = 253 + }; + + return test_uea2(&test); +} + +static int uea2_test_set_2(void) +{ + uea2_test_data_t test = { + .name = "UEA2 test set 2", + .key = "2BD6459F82C440E0952C49104805FF48", + .plaintext = "7EC61272 743BF161 4726446A 6C38CED1" + "66F6CA76 EB543004 4286346C EF130F92" + "922B0345 0D3A9975 E5BD2EA0 EB55AD8E" + "1B199E3E C4316020 E9A1B285 E7627953" + "59B7BDFD 39BEF4B2 484583D5 AFE082AE" + "E638BF5F D5A60619 3901A08F 4AB41AAB" + "9B134880", + .ciphertext = "3F678507 14B8DA69 EFB727ED 7A6C0C50" + "714AD736 C4F56000 06E3525B E807C467" + "C677FF86 4AF45FBA 09C27CDE 38F87A1F" + "84D59AB2 55408F2C 7B82F9EA D41A1FE6" + "5EABEBFB C1F3A4C5 6C9A26FC F7B3D66D" + "0220EE47 75BC5817 0A2B12F3 431D11B3" + "44D6E36C", + .count = 0xC675A64B, + .bearer = 0x0c, + .direction = 1, + .length_in_bits = 798 + }; + + return test_uea2(&test); +} + +static int uea2_test_set_3(void) +{ + uea2_test_data_t test = { + .name = "UEA2 test set 3", + .key = "0A8B6BD8D9B08B08D64E32D1817777FB", + .plaintext = "FD40A41D 370A1F65 74509568 7D47BA1D" + "36D2349E 23F64439 2C8EA9C4 9D40C132" + "71AFF264 D0F248", + .ciphertext = "48148E54 52A210C0 5F46BC80 DC6F7349" + "5B02048C 1B958B02 6102CA97 280279A4" + "C18D2EE3 08921C", + .count = 0x544D49CD, + .bearer = 0x04, + .direction = 0, + .length_in_bits = 310 + }; + + return test_uea2(&test); +} + +static int uea2_test_set_4(void) +{ + uea2_test_data_t test = { + .name = "UEA2 test set 4", + .key = "AA1F95AEA533BCB32EB63BF52D8F831A", + .plaintext = "FB1B96C5 C8BADFB2 E8E8EDFD E78E57F2" + "AD81E741 03FC430A 534DCC37 AFCEC70E" + "1517BB06 F27219DA E49022DD C47A068D" + "E4C9496A 951A6B09 EDBDC864 C7ADBD74" + "0AC50C02 2F3082BA FD22D781 97C5D508" + "B977BCA1 3F32E652 E74BA728 576077CE" + "628C535E 87DC6077 BA07D290 68590C8C" + "B5F1088E 082CFA0E C961302D 69CF3D44", + .ciphertext = "FFCFC2FE AD6C094E 96C589D0 F6779B67" + "84246C3C 4D1CEA20 3DB3901F 40AD4FD7" + "138BC6D7 7E8320CB 102F497F DD44A269" + "A96ECB28 617700E3 32EB2F73 6B34F4F2" + "693094E2 2FF94F9B E4723DA4 0C40DFD3" + "931CC1AC 9723F6B4 A9913E96 B6DB7ABC" + "ACE41517 7C1D0115 C5F09B5F DEA0B3AD" + "B8F9DA6E 9F9A04C5 43397B9D 43F87330", + .count = 0x72D8C671, + .bearer = 0x10, + .direction = 1, + .length_in_bits = 1022 + }; + + return test_uea2(&test); +} + +static int uea2_test_set_5(void) +{ + uea2_test_data_t test = { + .name = "UEA2 test set 5", + .key = "9618AE46891F86578EEBE90EF7A1202E", + .plaintext = "8DAA17B1 AE050529 C6827F28 C0EF6A12" + "42E93F8B 314FB18A 77F790AE 049FEDD6" + "12267FEC AEFC4501 74D76D9F 9AA7755A" + "30CD90A9 A5874BF4 8EAF70EE A3A62A25" + "0A8B6BD8 D9B08B08 D64E32D1 817777FB" + "544D49CD 49720E21 9DBF8BBE D33904E1" + "FD40A41D 370A1F65 74509568 7D47BA1D" + "36D2349E 23F64439 2C8EA9C4 9D40C132" + "71AFF264 D0F24841 D6465F09 96FF84E6" + "5FC517C5 3EFC3363 C38492A8", + .ciphertext = "6CDB18A7 CA8218E8 6E4B4B71 6A4D0437" + "1FBEC262 FC5AD0B3 819B187B 97E55B1A" + "4D7C19EE 24C8B4D7 723CFEDF 045B8ACA" + "E4869517 D80E5061 5D9035D5 D9C5A40A" + "F602280B 542597B0 CB18619E EB359257" + "59D195E1 00E8E4AA 0C38A3C2 ABE0F3D8" + "FF04F3C3 3C295069 C23694B5 BBEACDD5" + "42E28E8A 94EDB911 9F412D05 4BE1FA72" + "72B5FFB2 B2570F4F 7CEAF383 A8A9D935" + "72F04D6E 3A6E2937 26EC62C8", + .count = 0xC675A64B, + .bearer = 0x0c, + .direction = 1, + .length_in_bits = 1245 + }; + + return test_uea2(&test); +} + +static int uea2_test_set_6(void) +{ + uea2_test_data_t test = { + .name = "UEA2 test set 6", + .key = "54F4E2E04C83786EEC8FB5ABE8E36566", + .plaintext = "40981BA6 824C1BFB 4286B299 783DAF44" + "2C099F7A B0F58D5C 8E46B104 F08F01B4" + "1AB48547 2029B71D 36BD1A3D 90DC3A41" + "B46D5167 2AC4C966 3A2BE063 DA4BC8D2" + "808CE33E 2CCCBFC6 34E1B259 060876A0" + "FBB5A437 EBCC8D31 C19E4454 318745E3" + "FA16BB11 ADAE2488 79FE52DB 2543E53C" + "F445D3D8 28CE0BF5 C560593D 97278A59" + "762DD0C2 C9CD68D4 496A7925 08614014" + "B13B6AA5 1128C18C D6A90B87 978C2FF1" + "CABE7D9F 898A411B FDB84F68 F6727B14" + "99CDD30D F0443AB4 A6665333 0BCBA110" + "5E4CEC03 4C73E605 B4310EAA ADCFD5B0" + "CA27FFD8 9D144DF4 79275942 7C9CC1F8" + "CD8C8720 2364B8A6 87954CB0 5A8D4E2D" + "99E73DB1 60DEB180 AD0841E9 6741A5D5" + "9FE4189F 15420026 FE4CD121 04932FB3" + "8F735340 438AAF7E CA6FD5CF D3A195CE" + "5ABE6527 2AF607AD A1BE65A6 B4C9C069" + "3234092C 4D018F17 56C6DB9D C8A6D80B" + "88813861 6B681262 F954D0E7 71174878" + "0D92291D 86299972 DB741CFA 4F37B8B5" + "6CDB18A7 CA8218E8 6E4B4B71 6A4D0437" + "1FBEC262 FC5AD0B3 819B187B 97E55B1A" + "4D7C19EE 24C8B4D7 723CFEDF 045B8ACA" + "E4869517 D80E5061 5D9035D5 D9C5A40A" + "F602280B 542597B0 CB18619E EB359257" + "59D195E1 00E8E4AA 0C38A3C2 ABE0F3D8" + "FF04F3C3 3C295069 C23694B5 BBEACDD5" + "42E28E8A 94EDB911 9F412D05 4BE1FA72" + "B09550", + .ciphertext = "351E30D4 D910C5DD 5AD7834C 426E6C0C" + "AB6486DA 7B0FDA4C D83AF1B9 647137F1" + "AC43B434 223B19BE 07BD89D1 CC306944" + "D3361EA1 A2F8CDBD 32165597 6350D00B" + "80DD8381 20A7755C 6DEA2AB2 B0C99A91" + "3F47DAE2 B8DEB9A8 29E5469F F2E18777" + "6F6FD081 E3871D11 9A76E24C 917EA626" + "48E02E90 367564DE 72AE7E4F 0A4249A9" + "A5B0E465 A2D6D9DC 87843B1B 875CC9A3" + "BE93D8DA 8F56ECAF 5981FE93 C284318B" + "0DEC7A3B A108E2CB 1A61E966 FA7AFA7A" + "C7F67F65 BC4A2DF0 70D4E434 845F109A" + "B2B68ADE 3DC316CA 6332A628 93E0A7EC" + "0B4FC251 91BF2FF1 B9F9815E 4BA8A99C" + "643B5218 04F7D585 0DDE3952 206EC6CC" + "F340F9B3 220B3023 BDD06395 6EA83339" + "20FDE99E 0675410E 49EF3B4D 3FB3DF51" + "92F99CA8 3D3B0032 DE08C220 776A5865" + "B0E4B3B0 C75DEFE7 762DFF01 8EA7F5BE" + "2B2F972B 2A8BA597 0E43BD6F DD63DAE6" + "29784EC4 8D610054 EE4E4B5D BBF1FC2F" + "A0B830E9 4DCBB701 4E8AB429 AB100FC4" + "8F83171D 99FC258B 7C2BA7C1 76EAEAAD" + "37F860D5 97A31CE7 9B594733 C7141DF7" + "9151FCA9 0C08478A 5C6C2CC4 81D51FFE" + "CE3CD7D2 58134882 7A71F091 428EBE38" + "C95A3F5C 63E056DF B7CC45A9 B7C07D83" + "4E7B20B9 9ED20242 9C14BB85 FFA43B7C" + "B68495CD 75AB66D9 64D4CAFE 64DD9404" + "DAE2DC51 10617F19 4FC3C184 F583CD0D" + "EF6D00", + .count = 0xACA4F50F, + .bearer = 0x0b, + .direction = 0, + .length_in_bits = 3861 + }; + + return test_uea2(&test); +} + +/* integrity tests */ + +typedef struct { + char *name; + char *key; + char *data; + char *mac; + uint32_t count; + uint32_t fresh; + int direction; + int length_in_bits; +} uia2_test_data_t; + +static int test_uia2(uia2_test_data_t *test) +{ + unsigned char *data = s2b(test->data); + unsigned char *mac_expected = s2b(test->mac); + unsigned char mac_computed[4]; + unsigned char *key = s2b(test->key); + int count = test->count; + uint32_t fresh = test->fresh; + int direction = test->direction; + int length = BITS2BYTES(test->length_in_bits); + + printf("%s\n", test->name); + + print_buffer(key, 16, "KEY "); + print_buffer(data, length, "DATA "); + + _snow3g_integrity(count, fresh, direction, key, length, data, mac_computed); + + int ret = memcmp(mac_computed, mac_expected, 4) != 0; + + printf("COMPUTED[%d] ", length); for (int i = 0; i < 4; i++) printf(" %2.2x", mac_computed[i]); printf("\n"); + printf("EXPECTED[%d] ", length); for (int i = 0; i < 4; i++) printf(" %2.2x", mac_expected[i]); printf("\n"); + free(key); + free(mac_expected); + free(data); + + printf("%s\n", ret ? "FAIL" : "OK"); + + return ret; +} + +static int uia2_test_set_1(void) +{ + uia2_test_data_t test = { + .name = "UIA2 test set 1", + .key = "2BD6459F82C5B300952C49104881FF48", + .data = "3332346263393861 373479", + .mac = "EE419E0D", + .count = 0x38A6F056, + .fresh = 0xB8AEFDA9, + .direction = 0, + .length_in_bits = 88 + }; + + return test_uia2(&test); +} + +/* see comment in main() */ +__attribute__ ((unused)) +static int uia2_test_set_2(void) +{ + uia2_test_data_t test = { + .name = "UIA2 test set 2", + .key = "7E5E94431E11D73828D739CC6CED4573", + .data = "B3D3C9170A4E1632 F60F861013D22D84 B726B6A278D802D1 EEAF1321BA5929DC", + .mac = "92F2A453", + .count = 0x36AF6144, + .fresh = 0x9838F03A, + .direction = 1, + .length_in_bits = 254 + }; + + return test_uia2(&test); +} + +/* see comment in main() */ +__attribute__ ((unused)) +static int uia2_test_set_3(void) +{ + uia2_test_data_t test = { + .name = "UIA2 test set 3", + .key = "D3419BE821087ACD02123A9248033359", + .data = "BBB057038809496B CFF86D6FBC8CE5B1 35A06B166054F2D5 65BE8ACE75DC851E" + "0BCDD8F07141C495 872FB5D8C0C66A8B 6DA556663E4E4612 05D84580BEE5BC7E", + .mac = "AD8C69F9", + .count = 0xC7590EA9, + .fresh = 0x57D5DF7D, + .direction = 0, + .length_in_bits = 511 + }; + + return test_uia2(&test); +} + +static int uia2_test_set_4(void) +{ + uia2_test_data_t test = { + .name = "UIA2 test set 4", + .key = "83FD23A244A74CF358DA3019F1722635", + .data = "35C68716633C66FB 750C266865D53C11 EA05B1E9FA49C839 8D48E1EFA5909D39" + "47902837F5AE96D5 A05BC8D61CA8DBEF 1B13A4B4ABFE4FB1 006045B674BB5472" + "9304C382BE53A5AF 05556176F6EAA2EF 1D05E4B083181EE6 74CDA5A485F74D7A", + .mac = "7306D607", + .count = 0x36AF6144, + .fresh = 0x4F302AD2, + .direction = 1, + .length_in_bits = 768 + }; + + return test_uia2(&test); +} + +/* see comment in main() */ +__attribute__ ((unused)) +static int uia2_test_set_5(void) +{ + uia2_test_data_t test = { + .name = "UIA2 test set 5", + .key = "6832A65CFF4473621EBDD4BA26A921FE", + .data = "D3C5383962682071 7765667620323837 636240981BA6824C 1BFB1AB485472029" + "B71D808CE33E2CC3 C0B5FC1F3DE8A6DC", + .mac = "E3D36EF1", + .count = 0x36AF6144, + .fresh = 0x9838F03A, + .direction = 0, + .length_in_bits = 383 + }; + + return test_uia2(&test); +} + +/* see comment in main() */ +__attribute__ ((unused)) +static int uia2_test_set_6(void) +{ + uia2_test_data_t test = { + .name = "UIA2 test set 6", + .key = "5D0A80D8134AE19677824B671E838AF4", + .data = "70DEDF2DC42C5CBD 3A96F8A0B11418B3 608D5733604A2CD3 6AABC70CE3193BB5" + "153BE2D3C06DFDB2 D16E9C357158BE6A 41D6B861E491DB3F BFEB518EFCF048D7" + "D58953730FF30C9E C470FFCD663DC342 01C36ADDC0111C35 B38AFEE7CFDB582E" + "3731F8B4BAA8D1A8 9C06E81199A97162 27BE344EFCB436DD D0F096C064C3B5E2" + "C399993FC77394F9 E09720A811850EF2 3B2EE05D9E617360 9D86E1C0C18EA51A" + "012A00BB413B9CB8 188A703CD6BAE31C C67B34B1B00019E6 A2B2A690F02671FE" + "7C9EF8DEC0094E53 3763478D58D2C5F5 B827A0148C5948A9 6931ACF84F465A64" + "E62CE74007E991E3 7EA823FA0FB21923 B79905B733B631E6 C7D6860A3831AC35" + "1A9C730C52FF72D9 D308EEDBAB21FDE1 43A0EA17E23EDC1F 74CBB3638A2033AA" + "A15464EAA733385D BBEB6FD73509B857 E6A419DCA1D8907A F977FBAC4DFA35EC", + .mac = "C058D244", + .count = 0x7827FAB2, + .fresh = 0xA56C6CA2, + .direction = 1, + .length_in_bits = 2558 + }; + + return test_uia2(&test); +} + +static int uia2_test_set_7(void) +{ + uia2_test_data_t test = { + .name = "UIA2 test set 7", + .key = "B3120FFDB2CF6AF4E73EAF2EF4EBEC69", + .data = "0000000000000000 0101010101010101 E0958045F3A0BBA4 E3968346F0A3B8A7" + "C02A018AE6407652 26B987C913E6CBF0 83570016CF83EFBC 61C082513E21561A" + "427C009D28C298EF ACE78ED6D56C2D45 05AD032E9C04DC60 E73A81696DA665C6" + "C48603A57B45AB33 221585E68EE31691 87FB0239528632DD 656C807EA3248B7B" + "46D002B2B5C7458E B85B9CE95879E034 0859055E3B0ABBC3 EACE8719CAA80265" + "C97205D5DC4BCC90 2FE1839629ED7132 8A0F0449F588557E 6898860E042AECD8" + "4B2404C212C9222D A5BF8A89EF679787 0CF50771A60F66A2 EE62853657ADDF04" + "CDDE07FA414E11F1 2B4D81B9B4E8AC53 8EA30666688D881F 6C348421992F31B9" + "4F8806ED8FCCFF4C 9123B89642527AD6 13B109BF75167485 F1268BF884B4CD23" + "D29A0934925703D6 34098F7767F1BE74 91E708A8BB949A38 73708AEF4A36239E" + "50CC08235CD5ED6B BE578668A17B58C1 171D0B90E813A9E4 F58A89D719B11042" + "D6360B1B0F52DEB7 30A58D58FAF46315 954B0A8726914759 77DC88C0D733FEFF" + "54600A0CC1D0300A AAEB94572C6E95B0 1AE90DE04F1DCE47 F87E8FA7BEBF77E1" + "DBC20D6BA85CB914 3D518B285DFA04B6 98BF0CF7819F20FA 7A288EB0703D995C" + "59940C7C66DE57A9 B70F82379B70E203 1E450FCFD2181326 FCD28D8823BAAA80" + "DF6E0F4435596475 39FD8907C0FFD9D7 9C130ED81C9AFD9B 7E848C9FED38443D" + "5D380E53FBDB8AC8 C3D3F06876054F12 2461107DE92FEA09 C6F6923A188D53AF" + "E54A10F60E6E9D5A 03D996B5FBC820F8 A637116A27AD04B4 44A0932DD60FBD12" + "671C11E1C0EC73E7 89879FAA3D42C64D 20CD1252742A3768 C25A901585888ECE" + "E1E612D9936B403B 0775949A66CDFD99 A29B1345BAA8D9D5 400C91024B0A6073" + "63B013CE5DE9AE86 9D3B8D95B0570B3C 2D391422D32450CB CFAE96652286E96D" + "EC1214A934652798 0A8192EAC1C39A3A AF6F15351DA6BE76 4DF89772EC0407D0" + "6E4415BEFAE7C925 80DF9BF507497C8F 2995160D4E218DAA CB02944ABF83340C" + "E8BE1686A960FAF9 0E2D90C55CC6475B ABC3171A80A36317 4954955D7101DAB1" + "6AE8179167E21444 B443A9EAAA7C91DE 36D118C39D389F8D D4469A846C9A262B" + "F7FA18487A79E8DE 11699E0B8FDF557C B48719D453BA7130 56109B93A218C896" + "75AC195FB4FB0663 9B3797144955B3C9 327D1AEC003D42EC D0EA98ABF19FFB4A" + "F3561A67E77C35BF 15C59C2412DA881D B02B1BFBCEBFAC51 52BC99BC3F1D15F7" + "71001B7029FEDB02 8F8B852BC4407EB8 3F891C9CA733254F DD1E9EDB56919CE9" + "FEA21C174072521C 18319A54B5D4EFBE BDDF1D8B69B1CBF2 5F489FCC98137254" + "7CF41D008EF0BCA1 926F934B735E090B 3B251EB33A36F82E D9B29CF4CB944188" + "FA0E1E38DD778F7D 1C9D987B28D132DF B9731FA4F4B41693 5BE49DE30516AF35" + "78581F2F13F561C0 663361941EAB249A 4BC123F8D15CD711 A956A1BF20FE6EB7" + "8AEA2373361DA042 6C79A530C3BB1DE0 C99722EF1FDE39AC 2B00A0A8EE7C800A" + "08BC2264F89F4EFF E627AC2F0531FB55 4F6D21D74C590A70 ADFAA390BDFBB3D6" + "8E46215CAB187D23 68D5A71F5EBEC081 CD3B20C082DBE4CD 2FACA28773795D6B" + "0C10204B659A939E F29BBE1088243624 429927A7EB576DD3 A00EA5E01AF5D475" + "83B2272C0C161A80 6521A16FF9B0A722 C0CF26B025D5836E 2258A4F7D4773AC8" + "01E4263BC294F43D EF7FA8703F3A4197 463525887652B0B2 A4A2A7CF87F00914" + "871E25039113C7E1 618DA34064B57A43 C463249FB8D05E0F 26F4A6D84972E7A9" + "054824145F91295C DBE39A6F920FACC6 59712B46A54BA295 BBE6A90154E91B33" + "985A2BCD420AD5C6 7EC9AD8EB7AC6864 DB272A516BC94C28 39B0A8169A6BF58E" + "1A0C2ADA8C883B7B F497A49171268ED1 5DDD2969384E7FF4 BF4AAB2EC9ECC652" + "9CF629E2DF0F08A7 7A65AFA12AA9B505 DF8B287EF6CC9149 3D1CAA39076E28EF" + "1EA028F5118DE61A E02BB6AEFC3343A0 50292F199F401857 B2BEAD5E6EE2A1F1" + "91022F9278016F04 7791A9D18DA7D2A6 D27F2E0E51C2F6EA 30E8AC49A0604F4C" + "13542E85B68381B9 FDCFA0CE4B2D3413 54852D360245C536 B612AF71F3E77C90" + "95AE2DBDE504B265 733DABFE10A20FC7 D6D32C21CCC72B8B 3444AE663D65922D" + "17F82CAA2B865CD8 8913D291A6589902 6EA1328439723C19 8C36B0C3C8D085BF" + "AF8A320FDE334B4A 4919B44C2B95F6E8 ECF73393F7F0D2A4 0E60B1D406526B02" + "2DDC331810B1A5F7 C347BD53ED1F105D 6A0D30ABA477E178 889AB2EC55D558DE" + "AB2630204336962B 4DB5B663B6902B89 E85B31BC6AF50FC5 0ACCB3FB9B57B663" + "297031378DB47896 D7FBAF6C600ADD2C 67F936DB037986DB 856EB49CF2DB3F7D" + "A6D23650E438F188 4041B013119E4C2A E5AF37CCCDFB6866 0738B58B3C59D1C0" + "248437472ABA1F35 CA1FB90CD714AA9F 635534F49E7C5BBA 81C2B6B36FDEE21C" + "A27E347F793D2CE9 44EDB23C8C9B914B E10335E350FEB507 0394B7A4A15C0CA1" + "20283568B7BFC254 FE838B137A2147CE 7C113A3A4D65499D 9E86B87DBCC7F03B" + "BD3A3AB1AA243ECE 5BA9BCF25F82836C FE473B2D83E7A720 1CD0B96A72451E86" + "3F6C3BA664A6D073 D1F7B5ED990865D9 78BD3815D06094FC 9A2ABA5221C22D5A" + "B996389E3721E3AF 5F05BEDDC2875E0D FAEB39021EE27A41 187CBB45EF40C3E7" + "3BC03989F9A30D12 C54BA7D2141DA8A8 75493E65776EF35F 97DEBC2286CC4AF9" + "B4623EEE902F840C 52F1B8AD658939AE F71F3F72B9EC1DE2 1588BD35484EA444" + "36343FF95EAD6AB1 D8AFB1B2A303DF1B 71E53C4AEA6B2E3E 9372BE0D1BC99798" + "B0CE3CC10D2A596D 565DBA82F88CE4CF F3B33D5D24E9C083 1124BF1AD54B7925" + "32983DD6C3A8B7D0", + .mac = "179F2FA6", + .count = 0x296F393C, + .fresh = 0x6B227737, + .direction = 1, + .length_in_bits = 16448 + }; + + return test_uia2(&test); +} + +int main(void) +{ + int ret = 0; + + logInit(); + set_glog(OAILOG_DISABLE); + + if (uea2_test_set_1() != 0) + ret = -1; + if (uea2_test_set_2() != 0) + ret = -1; + if (uea2_test_set_3() != 0) + ret = -1; + if (uea2_test_set_4() != 0) + ret = -1; + if (uea2_test_set_5() != 0) + ret = -1; + if (uea2_test_set_6() != 0) + ret = -1; + + if (uia2_test_set_1() != 0) + ret = -1; +#if 0 + /* test disabled, length is not multiple of 8, this line in _snow3g_integrity() + * is wrong: + * eval ^= (uint64_t)length * 8; + * but! can be manually checked by replacing with this line: + * eval ^= 254; + * and recompiling + */ + if (uia2_test_set_2() != 0) + ret = -1; +#endif +#if 0 + /* also disabled, use 511 this time */ + if (uia2_test_set_3() != 0) + ret = -1; +#endif + if (uia2_test_set_4() != 0) + ret = -1; +#if 0 + /* also disabled, use 383 this time */ + if (uia2_test_set_5() != 0) + ret = -1; +#endif +#if 0 + /* also disabled, use 2558 this time */ + if (uia2_test_set_6() != 0) + ret = -1; +#endif + if (uia2_test_set_7() != 0) + ret = -1; + + return ret; +} From 952052127a5455f54470c9765329b389044f6403 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Sep 2024 10:47:44 +0200 Subject: [PATCH 5/5] Avoid ubsan error like this: /oai-ran/openair3/SECU/snow3g.c:429:23: runtime error: left shift of 232 by 24 places cannot be represented in type 'int' --- openair3/SECU/snow3g.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/openair3/SECU/snow3g.c b/openair3/SECU/snow3g.c index 2594ead431..63519890ab 100644 --- a/openair3/SECU/snow3g.c +++ b/openair3/SECU/snow3g.c @@ -417,14 +417,14 @@ static uint32_t DIVa(int c) static void lfsr_init(snow3g_t *s, uint32_t f) { - uint8_t s0_0 = (s->s[0] >> 24) & 0xff; - uint8_t s0_1 = (s->s[0] >> 16) & 0xff; - uint8_t s0_2 = (s->s[0] >> 8) & 0xff; - uint8_t s0_3 = s->s[0] & 0xff; - uint8_t s11_0 = (s->s[11] >> 24) & 0xff; - uint8_t s11_1 = (s->s[11] >> 16) & 0xff; - uint8_t s11_2 = (s->s[11] >> 8) & 0xff; - uint8_t s11_3 = s->s[11] & 0xff; + uint32_t s0_0 = (s->s[0] >> 24) & 0xff; + uint32_t s0_1 = (s->s[0] >> 16) & 0xff; + uint32_t s0_2 = (s->s[0] >> 8) & 0xff; + uint32_t s0_3 = s->s[0] & 0xff; + uint32_t s11_0 = (s->s[11] >> 24) & 0xff; + uint32_t s11_1 = (s->s[11] >> 16) & 0xff; + uint32_t s11_2 = (s->s[11] >> 8) & 0xff; + uint32_t s11_3 = s->s[11] & 0xff; uint32_t v0 = (s0_1 << 24) | (s0_2 << 16) @@ -464,14 +464,14 @@ static void lfsr_init(snow3g_t *s, uint32_t f) static void lfsr_keystream(snow3g_t *s) { - uint8_t s0_0 = (s->s[0] >> 24) & 0xff; - uint8_t s0_1 = (s->s[0] >> 16) & 0xff; - uint8_t s0_2 = (s->s[0] >> 8) & 0xff; - uint8_t s0_3 = s->s[0] & 0xff; - uint8_t s11_0 = (s->s[11] >> 24) & 0xff; - uint8_t s11_1 = (s->s[11] >> 16) & 0xff; - uint8_t s11_2 = (s->s[11] >> 8) & 0xff; - uint8_t s11_3 = s->s[11] & 0xff; + uint32_t s0_0 = (s->s[0] >> 24) & 0xff; + uint32_t s0_1 = (s->s[0] >> 16) & 0xff; + uint32_t s0_2 = (s->s[0] >> 8) & 0xff; + uint32_t s0_3 = s->s[0] & 0xff; + uint32_t s11_0 = (s->s[11] >> 24) & 0xff; + uint32_t s11_1 = (s->s[11] >> 16) & 0xff; + uint32_t s11_2 = (s->s[11] >> 8) & 0xff; + uint32_t s11_3 = s->s[11] & 0xff; uint32_t v0 = (s0_1 << 24) | (s0_2 << 16)