Commit 18f7a702 authored by Cedric Roux's avatar Cedric Roux

snow3g: provide a faster implementation

parent 73ae18da
...@@ -20,86 +20,22 @@ ...@@ -20,86 +20,22 @@
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#include "assertions.h" #include "assertions.h"
#include "conversions.h"
#include "nas_stream_eea1.h" #include "nas_stream_eea1.h"
#include "snow3g.h" #include "snow3g.h"
void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t *out) 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; uint8_t *key = (uint8_t *)stream_cipher->context;
snow3g_ciphering(stream_cipher->count,
DevAssert(stream_cipher != NULL); stream_cipher->bearer,
DevAssert(out != NULL); stream_cipher->direction,
key,
n = ( stream_cipher->blength + 31 ) / 32; stream_cipher->blength / 8,
zero_bit = stream_cipher->blength & 0x7; stream_cipher->message,
//byte_length = stream_cipher->blength >> 3; out);
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; i<n; i++) {
KS[i] = hton_int32(KS[i]);
}
/* Exclusive-OR the input data with keystream to generate the output bit
stream */
for (i=0; i<n*4; i++) {
stream_cipher->message[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];
}
} }
stream_security_context_t *stream_ciphering_init_eea1(const uint8_t *ciphering_key) stream_security_context_t *stream_ciphering_init_eea1(const uint8_t *ciphering_key)
......
...@@ -24,9 +24,6 @@ ...@@ -24,9 +24,6 @@
#include "secu_defs.h" #include "secu_defs.h"
#include <stdlib.h>
#include <stdint.h>
void nas_stream_encrypt_eea1(nas_stream_cipher_t const *stream_cipher, uint8_t *out); 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); stream_security_context_t *stream_ciphering_init_eea1(const uint8_t *ciphering_key);
......
...@@ -19,105 +19,12 @@ ...@@ -19,105 +19,12 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#include <math.h> // double ceil(double x);
#include "nas_stream_eia1.h" #include "nas_stream_eia1.h"
#include "assertions.h" #include "assertions.h"
#include "conversions.h"
#include "snow3g.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. * @brief Create integrity cmac t for a given message.
* @param[in] stream_cipher Structure containing various variables to setup encoding * @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) ...@@ -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]) 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; uint8_t *key = (uint8_t *)stream_cipher->context;
snow3g_integrity(stream_cipher->count,
/* Load the Integrity Key for SNOW3G initialization as in section 4.4. */ stream_cipher->bearer,
memcpy(K+3,key+0,4); /*K[3] = key[0]; we assume stream_cipher->direction,
K[3]=key[0]||key[1]||...||key[31] , with key[0] the key,
* most important bit of key*/ stream_cipher->blength / 8,
memcpy(K+2,key+4,4); /*K[2] = key[1];*/ stream_cipher->message,
memcpy(K+1,key+8,4); /*K[1] = key[2];*/ out);
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; i<D-2; i++) {
V = EVAL ^ U64(&message[4 * 2*i], 8);
EVAL = MUL64(V,P,c);
}
/* for D-2 */
rem_bits = stream_cipher->blength % 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);
} }
stream_security_context_t *stream_integrity_init_eia1(const uint8_t *integrity_key) stream_security_context_t *stream_integrity_init_eia1(const uint8_t *integrity_key)
......
...@@ -19,326 +19,851 @@ ...@@ -19,326 +19,851 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
#include <stdlib.h> #define NO_MAIN
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "rijndael.h"
#include "snow3g.h" #include "snow3g.h"
static uint8_t _MULx(uint8_t V, uint8_t c); #include <arpa/inet.h>
static uint8_t _MULxPOW(uint8_t V, uint8_t i, uint8_t c); #include <stdint.h>
static uint32_t _MULalpha(uint8_t c);
static uint32_t _DIValpha(uint8_t c); typedef struct {
static uint32_t _S1(uint32_t w); /* _s is twice as big as defined in the specs to avoid moving memory,
static uint32_t _S2(uint32_t w); * we only change the pointer 's', see lfsr_keystream()
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); uint32_t _s[16 * 2];
static uint32_t _snow3g_clock_fsm(snow_3g_context_t *snow_3g_context_pP); uint32_t *s;
void snow3g_initialize(uint32_t k[4], uint32_t IV[4], snow_3g_context_t *snow_3g_context_pP); uint32_t r1, r2, r3;
void snow3g_generate_key_stream(uint32_t n, uint32_t *ks, snow_3g_context_t *snow_3g_context_pP); } snow3g_t;
static const uint32_t s1_t0[256] = {
/* _MULx. 0xA56363C6, 0x847C7CF8, 0x997777EE, 0x8D7B7BF6, 0xDF2F2FF, 0xBD6B6BD6, 0xB16F6FDE, 0x54C5C591,
* Input V: an 8-bit input. 0x50303060, 0x3010102, 0xA96767CE, 0x7D2B2B56, 0x19FEFEE7, 0x62D7D7B5, 0xE6ABAB4D, 0x9A7676EC,
* Input c: an 8-bit input. 0x45CACA8F, 0x9D82821F, 0x40C9C989, 0x877D7DFA, 0x15FAFAEF, 0xEB5959B2, 0xC947478E, 0xBF0F0FB,
* Output : an 8-bit input. 0xECADAD41, 0x67D4D4B3, 0xFDA2A25F, 0xEAAFAF45, 0xBF9C9C23, 0xF7A4A453, 0x967272E4, 0x5BC0C09B,
* MULx maps 16 bits to 8 bits 0xC2B7B775, 0x1CFDFDE1, 0xAE93933D, 0x6A26264C, 0x5A36366C, 0x413F3F7E, 0x2F7F7F5, 0x4FCCCC83,
*/ 0x5C343468, 0xF4A5A551, 0x34E5E5D1, 0x8F1F1F9, 0x937171E2, 0x73D8D8AB, 0x53313162, 0x3F15152A,
0xC040408, 0x52C7C795, 0x65232346, 0x5EC3C39D, 0x28181830, 0xA1969637, 0xF05050A, 0xB59A9A2F,
static uint8_t _MULx(uint8_t V, uint8_t c) 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 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 int w0 = (w >> 24) & 0xff;
if ( V & 0x80 ) int w1 = (w >> 16) & 0xff;
return ( (V << 1) ^ c); int w2 = (w >> 8) & 0xff;
else int w3 = w & 0xff;
return ( V << 1);
}
/* _MULxPOW. return s1_t0[w3] ^ s1_t1[w2] ^ s1_t2[w1] ^ s1_t3[w0];
* 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 uint8_t _MULxPOW(uint8_t V, uint8_t i, uint8_t c) 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 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) int w0 = (w >> 24) & 0xff;
return V; int w1 = (w >> 16) & 0xff;
else int w2 = (w >> 8) & 0xff;
return _MULx( _MULxPOW( V, i-1, c ), c); int w3 = w & 0xff;
}
/* The function _MULalpha. return s2_t0[w3] ^ s2_t1[w2] ^ s2_t2[w1] ^ s2_t3[w0];
* Input c: 8-bit input. }
* Output : 32-bit output.
* maps 8 bits to 32 bits.
*/
static uint32_t _MULalpha(uint8_t c) 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 MULa(int c)
{ {
return ( ( ((uint32_t)_MULxPOW(c,23, 0xa9)) << 24 ) | return mula[c];
( ((uint32_t)_MULxPOW(c, 245, 0xa9)) << 16 ) |
( ((uint32_t)_MULxPOW(c, 48, 0xa9)) << 8 ) |
( ((uint32_t)_MULxPOW(c, 239, 0xa9)) ) ) ;
} }
static const uint32_t diva[256] = {
/* The function DIV alpha. 0x00000000, 0x180F40CD, 0x301E8033, 0x2811C0FE, 0x603CA966, 0x7833E9AB, 0x50222955, 0x482D6998,
* Input c: 8-bit input. 0xC078FBCC, 0xD877BB01, 0xF0667BFF, 0xE8693B32, 0xA04452AA, 0xB84B1267, 0x905AD299, 0x88559254,
* Output : 32-bit output. 0x29F05F31, 0x31FF1FFC, 0x19EEDF02, 0x01E19FCF, 0x49CCF657, 0x51C3B69A, 0x79D27664, 0x61DD36A9,
* maps 8 bits to 32 bit. 0xE988A4FD, 0xF187E430, 0xD99624CE, 0xC1996403, 0x89B40D9B, 0x91BB4D56, 0xB9AA8DA8, 0xA1A5CD65,
*/ 0x5249BE62, 0x4A46FEAF, 0x62573E51, 0x7A587E9C, 0x32751704, 0x2A7A57C9, 0x026B9737, 0x1A64D7FA,
0x923145AE, 0x8A3E0563, 0xA22FC59D, 0xBA208550, 0xF20DECC8, 0xEA02AC05, 0xC2136CFB, 0xDA1C2C36,
static uint32_t _DIValpha(uint8_t c) 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,
};
static uint32_t DIVa(int c)
{ {
return ( ( ((uint32_t)_MULxPOW(c, 16, 0xa9)) << 24 ) | return diva[c];
( ((uint32_t)_MULxPOW(c, 39, 0xa9)) << 16 ) |
( ((uint32_t)_MULxPOW(c, 6, 0xa9)) << 8 ) |
( ((uint32_t)_MULxPOW(c, 64, 0xa9)) ) ) ;
} }
/* The 32x32-bit S-Box S1 static void lfsr_init(snow3g_t *s, uint32_t f)
* 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)
{ {
uint8_t r0=0, r1=0, r2=0, r3=0; uint8_t s0_0 = (s->s[0] >> 24) & 0xff;
uint8_t srw0 = SR[ (uint8_t)((w >> 24) & 0xff) ]; uint8_t s0_1 = (s->s[0] >> 16) & 0xff;
uint8_t srw1 = SR[ (uint8_t)((w >> 16) & 0xff) ]; uint8_t s0_2 = (s->s[0] >> 8) & 0xff;
uint8_t srw2 = SR[ (uint8_t)((w >> 8) & 0xff) ]; uint8_t s0_3 = s->s[0] & 0xff;
uint8_t srw3 = SR[ (uint8_t)((w) & 0xff) ]; uint8_t s11_0 = (s->s[11] >> 24) & 0xff;
uint8_t s11_1 = (s->s[11] >> 16) & 0xff;
r0 = ( ( _MULx( srw0 , 0x1b) ) ^ uint8_t s11_2 = (s->s[11] >> 8) & 0xff;
( srw1 ) ^ uint8_t s11_3 = s->s[11] & 0xff;
( srw2 ) ^
( (_MULx( srw3, 0x1b)) ^ srw3 ) uint32_t v0 = (s0_1 << 24)
); | (s0_2 << 16)
| (s0_3 << 8);
r1 = ( ( ( _MULx( srw0 , 0x1b) ) ^ srw0 ) ^ uint32_t v11 = (s11_0 << 16)
( _MULx(srw1, 0x1b) ) ^ | (s11_1 << 8)
( srw2 ) ^ | s11_2;
( srw3 ) uint32_t v = v0 ^ MULa(s0_0) ^ s->s[2] ^ v11 ^ DIVa(s11_3) ^ f;
);
#if 0
r2 = ( ( srw0 ) ^ /* the specs do this */
( ( _MULx( srw1 , 0x1b) ) ^ srw1 ) ^ s->s[0] = s->s[1];
( _MULx(srw2, 0x1b) ) ^ s->s[1] = s->s[2];
( srw3 ) s->s[2] = s->s[3];
); s->s[3] = s->s[4];
s->s[4] = s->s[5];
r3 = ( ( srw0 ) ^ s->s[5] = s->s[6];
( srw1 ) ^ s->s[6] = s->s[7];
( ( _MULx( srw2 , 0x1b) ) ^ srw2 ) ^ s->s[7] = s->s[8];
( _MULx( srw3, 0x1b) ) s->s[8] = s->s[9];
); s->s[9] = s->s[10];
s->s[10] = s->s[11];
return ( ( ((uint32_t)r0) << 24 ) | ( ((uint32_t)r1) << 16 ) | ( ((uint32_t)r2) << 8 ) | ( ((uint32_t)r3) ) ); 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
/* 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 static void lfsr_keystream(snow3g_t *s)
* 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)
{ {
uint8_t r0=0, r1=0, r2=0, r3=0; uint8_t s0_0 = (s->s[0] >> 24) & 0xff;
uint8_t sqw0 = SQ[ (uint8_t)((w >> 24) & 0xff) ]; uint8_t s0_1 = (s->s[0] >> 16) & 0xff;
uint8_t sqw1 = SQ[ (uint8_t)((w >> 16) & 0xff) ]; uint8_t s0_2 = (s->s[0] >> 8) & 0xff;
uint8_t sqw2 = SQ[ (uint8_t)((w >> 8) & 0xff) ]; uint8_t s0_3 = s->s[0] & 0xff;
uint8_t sqw3 = SQ[ (uint8_t)((w) & 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;
r0 = ( ( _MULx( sqw0 , 0x69) ) ^ uint8_t s11_3 = s->s[11] & 0xff;
( sqw1 ) ^
( sqw2 ) ^ uint32_t v0 = (s0_1 << 24)
( (_MULx( sqw3, 0x69)) ^ sqw3 ) | (s0_2 << 16)
); | (s0_3 << 8);
uint32_t v11 = (s11_0 << 16)
r1 = ( ( ( _MULx( sqw0 , 0x69) ) ^ sqw0 ) ^ | (s11_1 << 8)
( _MULx(sqw1, 0x69) ) ^ | s11_2;
( sqw2 ) ^ uint32_t v = v0 ^ MULa(s0_0) ^ s->s[2] ^ v11 ^ DIVa(s11_3);
( sqw3 )
); #if 0
/* the specs do this */
r2 = ( ( sqw0 ) ^ s->s[0] = s->s[1];
( ( _MULx( sqw1 , 0x69) ) ^ sqw1 ) ^ s->s[1] = s->s[2];
( _MULx(sqw2, 0x69) ) ^ s->s[2] = s->s[3];
( sqw3 ) s->s[3] = s->s[4];
); s->s[4] = s->s[5];
s->s[5] = s->s[6];
r3 = ( ( sqw0 ) ^ s->s[6] = s->s[7];
( sqw1 ) ^ s->s[7] = s->s[8];
( ( _MULx( sqw2 , 0x69) ) ^ sqw2 ) ^ s->s[8] = s->s[9];
( _MULx( sqw3, 0x69) ) s->s[9] = s->s[10];
); s->s[10] = s->s[11];
s->s[11] = s->s[12];
return ( ( ((uint32_t)r0) << 24 ) | ( ((uint32_t)r1) << 16 ) | ( ((uint32_t)r2) << 8 ) | ( ((uint32_t)r3) ) ); s->s[12] = s->s[13];
s->s[13] = s->s[14];
s->s[14] = s->s[15];
s->s[15] = v;
#endif
/* 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. static uint32_t clock_fsm(snow3g_t *s)
* 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. uint32_t f = (s->s[15] + s->r1) ^ s->r2;
* See section 3.4.4.
*/ uint32_t r = s->r2 + (s->r3 ^ s->s[5]);
s->r3 = s2(s->r2);
s->r2 = s1(s->r1);
s->r1 = r;
static void _snow3g_clock_LFSR_initialization_mode(uint32_t F, snow_3g_context_t *s3g_ctx_pP) return f;
}
static uint32_t GET32(uint8_t *b)
{ {
uint32_t v = ( ( (s3g_ctx_pP->LFSR_S0 << 8) & 0xffffff00 ) ^ return ((uint32_t)b[0] << 24)
( _MULalpha( (uint8_t)((s3g_ctx_pP->LFSR_S0>>24) & 0xff) ) ) ^ | ((uint32_t)b[1] << 16)
( s3g_ctx_pP->LFSR_S2 ) ^ | ((uint32_t)b[2] << 8)
( (s3g_ctx_pP->LFSR_S11 >> 8) & 0x00ffffff ) ^ | (uint32_t)b[3];
( _DIValpha( (uint8_t)( ( s3g_ctx_pP->LFSR_S11) & 0xff ) ) ) ^
( F )
);
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;
} }
/* Clocking LFSR in keystream mode. static void snow3g_init(snow3g_t *s, uint8_t *_k, uint8_t *_iv)
* 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)
{ {
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);
s->s = &s->_s[0];
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;
for (int i = 0; i < 32; i++) {
uint32_t f = clock_fsm(s);
lfsr_init(s, f);
}
uint32_t v = ( ( (snow_3g_context_pP->LFSR_S0 << 8) & 0xffffff00 ) ^ /* start keystream generation (this is beginning of spec 4.2) */
( _MULalpha( (uint8_t)((snow_3g_context_pP->LFSR_S0>>24) & 0xff) ) ) ^ clock_fsm(s);
( snow_3g_context_pP->LFSR_S2 ) ^ lfsr_keystream(s);
( (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;
} }
/* Clocking FSM. static uint32_t generate_keystream_step(snow3g_t *s)
* 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)
{ {
uint32_t F = ( ( snow_3g_context_pP->LFSR_S15 + snow_3g_context_pP->FSM_R1 ) & 0xffffffff ) ^ snow_3g_context_pP->FSM_R2 ; uint32_t f = clock_fsm(s);
uint32_t r = ( snow_3g_context_pP->FSM_R2 + ( snow_3g_context_pP->FSM_R3 ^ snow_3g_context_pP->LFSR_S5 ) ) & 0xffffffff ; uint32_t ret = f ^ s->s[0];
lfsr_keystream(s);
snow_3g_context_pP->FSM_R3 = _S2(snow_3g_context_pP->FSM_R2); return ret;
snow_3g_context_pP->FSM_R2 = _S1(snow_3g_context_pP->FSM_R1); }
snow_3g_context_pP->FSM_R1 = r;
return F; 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];
} }
/* Initialization. static int MIN(int a, int b)
* Input k[4]: Four 32-bit words making up 128-bit key. {
* Input IV[4]: Four 32-bit words making 128-bit initialization variable. if (a < b) return a;
* Output: All the LFSRs and FSM are initialized for key generation. return b;
* See Section 4.1. }
*/
void snow3g_initialize(uint32_t k[4], uint32_t IV[4], snow_3g_context_t *snow_3g_context_pP) 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];
}
uint8_t i = 0; return (a << (32+24)) | (b << (32+16)) | (c << (32+8)) | (d << 32)
uint32_t F = 0x0; | (e << 24) | (f << 16) | (g << 8) | h;
}
snow_3g_context_pP->LFSR_S15 = k[3] ^ IV[0]; static uint64_t MULx64(uint64_t v, uint64_t c)
snow_3g_context_pP->LFSR_S14 = k[2]; {
snow_3g_context_pP->LFSR_S13 = k[1]; if (v & ((uint64_t)1 << 63))
snow_3g_context_pP->LFSR_S12 = k[0] ^ IV[1]; return (v << 1) ^ c;
return v << 1;
}
snow_3g_context_pP->LFSR_S11 = k[3] ^ 0xffffffff; static uint64_t MULxPOW64(uint64_t v, int i, uint64_t c)
snow_3g_context_pP->LFSR_S10 = k[2] ^ 0xffffffff ^ IV[2]; {
snow_3g_context_pP->LFSR_S9 = k[1] ^ 0xffffffff ^ IV[3]; if (i == 0) return v;
snow_3g_context_pP->LFSR_S8 = k[0] ^ 0xffffffff; return MULx64(MULxPOW64(v, i-1, c), c);
}
snow_3g_context_pP->LFSR_S7 = k[3]; static uint64_t MUL64(uint64_t v, uint64_t p, uint64_t c)
snow_3g_context_pP->LFSR_S6 = k[2]; {
snow_3g_context_pP->LFSR_S5 = k[1]; uint64_t result = 0;
snow_3g_context_pP->LFSR_S4 = k[0]; for (int i = 0; i < 64; i++) {
if ((p >> i) & 1)
result ^= MULxPOW64(v, i, c);
}
return result;
}
snow_3g_context_pP->LFSR_S3 = k[3] ^ 0xffffffff; static inline uint64_t mul_p(const uint64_t pm[7][256], uint64_t x)
snow_3g_context_pP->LFSR_S2 = k[2] ^ 0xffffffff; {
snow_3g_context_pP->LFSR_S1 = k[1] ^ 0xffffffff; uint64_t x0 = (x >> (32 + 24)) & 255;
snow_3g_context_pP->LFSR_S0 = k[0] ^ 0xffffffff; 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];
}
snow_3g_context_pP->FSM_R1 = 0x0; 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)
snow_3g_context_pP->FSM_R2 = 0x0; {
snow_3g_context_pP->FSM_R3 = 0x0; 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(i=0; i<32; i++) { for (int i = 0; i <= 7; i++) {
F = _snow3g_clock_fsm(snow_3g_context_pP); for (int j = 1; j <= 7; j++) {
_snow3g_clock_LFSR_initialization_mode(F, snow_3g_context_pP); 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;
} }
/* Generation of Keystream. void snow3g_integrity(uint32_t count, int bearer, int direction, const uint8_t *key, int length, const uint8_t *in, uint8_t *out)
* 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)
{ {
uint32_t t = 0; _snow3g_integrity(count, (uint32_t)bearer << 27, direction, key, length, in, out);
uint32_t F = 0x0; }
_snow3g_clock_fsm(snow_3g_context_pP); /* Clock FSM once. Discard the output. */ #ifndef NO_MAIN
_snow3g_clock_LFSR_key_stream_mode(snow_3g_context_pP); /* Clock LFSR in keystream mode once. */
for ( t=0; t<n; t++) { #include <stdio.h>
F = _snow3g_clock_fsm(snow_3g_context_pP); /* STEP 1 */ #include <stdlib.h>
ks[t] = F ^ snow_3g_context_pP->LFSR_S0; /* STEP 2 */ #include <time.h>
/* Note that ks[t] corresponds to z_{t+1} in section 4.2*/ 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]);
}
_snow3g_clock_LFSR_key_stream_mode(snow_3g_context_pP); /* STEP 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 */
...@@ -19,59 +19,24 @@ ...@@ -19,59 +19,24 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
/*! \file snow3g.h #ifndef _SNOW3G_H_
* \brief #define _SNOW3G_H_
* \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_
typedef struct snow_3g_context_s { #include <stdint.h>
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;
/* FSM : The Finite State Machine has three 32-bit registers R1, R2 and R3. void snow3g_ciphering(uint32_t count,
*/ int bearer,
uint32_t FSM_R1; int direction,
uint32_t FSM_R2; const uint8_t *key,
uint32_t FSM_R3; int length,
} snow_3g_context_t; const uint8_t *in,
uint8_t *out);
/* Initialization. void snow3g_integrity(uint32_t count,
* Input k[4]: Four 32-bit words making up 128-bit key. int bearer,
* Input IV[4]: Four 32-bit words making 128-bit initialization variable. int direction,
* Output: All the LFSRs and FSM are initialized for key generation. const uint8_t *key,
*/ int length,
void snow3g_initialize(uint32_t k[4], uint32_t IV[4], snow_3g_context_t *snow_3g_context_pP); const uint8_t *in,
uint8_t *out);
/* 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_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment