From bd74c259ec8ca24be40df9126be6e05d7bc8042d Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Wed, 13 Sep 2023 23:15:28 +0900 Subject: [PATCH] [AMF/MME] Fix crash during snow-3g encrypt (#2581) There was a memory problem in the encryption using snow_3g_f8, so AMF/MME crashed. To solve this problem, we used the snow-3g encryption library created as below. https://github.com/rcatolino/libressl-snow3g However, it seems that this library cannot be used to create integrity hash like snow_3g_f8. So, we decided to keep both snow-3g libraries for the time being. 1. lib/crypt/snow3g* : for INTEGRITY (NIA1, EIA1) 2. lib/crypt/openssl/snow3g* : for ENCRYPTION (NEA1, EEA1) --- lib/crypt/meson.build | 3 + lib/crypt/ogs-crypt.h | 2 + lib/crypt/openssl/snow3g.h | 116 +++++ lib/crypt/openssl/snow_core.c | 938 ++++++++++++++++++++++++++++++++++ lib/nas/common/security.c | 6 + tests/unit/security-test.c | 9 + 6 files changed, 1074 insertions(+) create mode 100644 lib/crypt/openssl/snow3g.h create mode 100644 lib/crypt/openssl/snow_core.c diff --git a/lib/crypt/meson.build b/lib/crypt/meson.build index b501cf5c2..2d42d1393 100644 --- a/lib/crypt/meson.build +++ b/lib/crypt/meson.build @@ -47,6 +47,9 @@ libcrypt_sources = files(''' curve25519-donna.c ecc.c + + openssl/snow3g.h + openssl/snow_core.c '''.split()) libcrypt_inc = include_directories('.') diff --git a/lib/crypt/ogs-crypt.h b/lib/crypt/ogs-crypt.h index 659d460ad..f0a8c69e7 100644 --- a/lib/crypt/ogs-crypt.h +++ b/lib/crypt/ogs-crypt.h @@ -40,6 +40,8 @@ #include "crypt/ogs-kdf.h" #include "crypt/ogs-base64.h" +#include "crypt/openssl/snow3g.h" + #undef OGS_CRYPT_INSIDE #ifdef __cplusplus diff --git a/lib/crypt/openssl/snow3g.h b/lib/crypt/openssl/snow3g.h new file mode 100644 index 000000000..bba7b3fb8 --- /dev/null +++ b/lib/crypt/openssl/snow3g.h @@ -0,0 +1,116 @@ +/* $OpenBSD: snow3g.h,v 0.10 2015 raphael.catolino@gmail.com$ */ +/* ==================================================================== + * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http: + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http: + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + */ + +#ifndef HEADER_SNOW3G_H +#define HEADER_SNOW3G_H + +#if 0 /* modified by acetcom */ +#include +#endif + +#ifdef OPENSSL_NO_SNOW3G +#error SNOW3G is disabled. +#endif + +#include +#include + +#define SNOW_ENCRYPT 1 +#define SNOW_DECRYPT 0 + +#define SNOW_WORD_SIZE 4 +#define SNOW_KEY_SIZE 16 + +#ifdef __cplusplus +extern "C" { +#endif + +struct snow_key_st { + uint32_t key[4]; + uint32_t iv[4]; +}; + +struct fsm_st { + uint32_t r1; + uint32_t r2; + uint32_t r3; +}; + +typedef struct snow_ctx_st { + uint32_t lfsr[SNOW_KEY_SIZE]; + struct fsm_st fsm; +} SNOW_CTX; + +struct snow_key_st +#if 0 +snow_array_to_key(const unsigned char key[16], const unsigned char iv[16]); +#else +snow_array_to_key(const unsigned char *key, const unsigned char *iv); +#endif + +void +SNOW_set_key(struct snow_key_st key_iv, SNOW_CTX *ctx); + +void +SNOW_gen_keystream(uint32_t *stream, size_t nb_word, SNOW_CTX *ctx); + +void +SNOW_init(uint32_t countc, uint8_t bearer, uint8_t direction, + const char *confidentiality_key, SNOW_CTX *ctx); + +void +SNOW(size_t nb_byte, const unsigned char *in, unsigned char *out, SNOW_CTX *ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* !HEADER_SNOW_H */ diff --git a/lib/crypt/openssl/snow_core.c b/lib/crypt/openssl/snow_core.c new file mode 100644 index 000000000..f705afa5a --- /dev/null +++ b/lib/crypt/openssl/snow_core.c @@ -0,0 +1,938 @@ +/* $OpenBSD: snow_core.c,v 0.10 2015 raphael.catolino@gmail.com$ */ + +/** + * snow 3g stream cipher. + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Implementation of the 3GPP UEA2 algorithm, aka the snow-3g stream cipher. + * The specification can be found at : + * http://www.gsma.com/technicalprojects/wp-content/uploads/2012/04/snow3gspec.pdf + */ + +#include +#include +#include +#include +#include + +/* Base components used in snow 3g specification */ + +/* Rijndael lookup tables for S-Boxes */ +static const uint32_t S1_T0[256] = { + 0xa56363c6U, 0x847c7cf8U, 0x997777eeU, 0x8d7b7bf6U, + 0x0df2f2ffU, 0xbd6b6bd6U, 0xb16f6fdeU, 0x54c5c591U, + 0x50303060U, 0x03010102U, 0xa96767ceU, 0x7d2b2b56U, + 0x19fefee7U, 0x62d7d7b5U, 0xe6abab4dU, 0x9a7676ecU, + 0x45caca8fU, 0x9d82821fU, 0x40c9c989U, 0x877d7dfaU, + 0x15fafaefU, 0xeb5959b2U, 0xc947478eU, 0x0bf0f0fbU, + 0xecadad41U, 0x67d4d4b3U, 0xfda2a25fU, 0xeaafaf45U, + 0xbf9c9c23U, 0xf7a4a453U, 0x967272e4U, 0x5bc0c09bU, + 0xc2b7b775U, 0x1cfdfde1U, 0xae93933dU, 0x6a26264cU, + 0x5a36366cU, 0x413f3f7eU, 0x02f7f7f5U, 0x4fcccc83U, + 0x5c343468U, 0xf4a5a551U, 0x34e5e5d1U, 0x08f1f1f9U, + 0x937171e2U, 0x73d8d8abU, 0x53313162U, 0x3f15152aU, + 0x0c040408U, 0x52c7c795U, 0x65232346U, 0x5ec3c39dU, + 0x28181830U, 0xa1969637U, 0x0f05050aU, 0xb59a9a2fU, + 0x0907070eU, 0x36121224U, 0x9b80801bU, 0x3de2e2dfU, + 0x26ebebcdU, 0x6927274eU, 0xcdb2b27fU, 0x9f7575eaU, + 0x1b090912U, 0x9e83831dU, 0x742c2c58U, 0x2e1a1a34U, + 0x2d1b1b36U, 0xb26e6edcU, 0xee5a5ab4U, 0xfba0a05bU, + 0xf65252a4U, 0x4d3b3b76U, 0x61d6d6b7U, 0xceb3b37dU, + 0x7b292952U, 0x3ee3e3ddU, 0x712f2f5eU, 0x97848413U, + 0xf55353a6U, 0x68d1d1b9U, 0x00000000U, 0x2cededc1U, + 0x60202040U, 0x1ffcfce3U, 0xc8b1b179U, 0xed5b5bb6U, + 0xbe6a6ad4U, 0x46cbcb8dU, 0xd9bebe67U, 0x4b393972U, + 0xde4a4a94U, 0xd44c4c98U, 0xe85858b0U, 0x4acfcf85U, + 0x6bd0d0bbU, 0x2aefefc5U, 0xe5aaaa4fU, 0x16fbfbedU, + 0xc5434386U, 0xd74d4d9aU, 0x55333366U, 0x94858511U, + 0xcf45458aU, 0x10f9f9e9U, 0x06020204U, 0x817f7ffeU, + 0xf05050a0U, 0x443c3c78U, 0xba9f9f25U, 0xe3a8a84bU, + 0xf35151a2U, 0xfea3a35dU, 0xc0404080U, 0x8a8f8f05U, + 0xad92923fU, 0xbc9d9d21U, 0x48383870U, 0x04f5f5f1U, + 0xdfbcbc63U, 0xc1b6b677U, 0x75dadaafU, 0x63212142U, + 0x30101020U, 0x1affffe5U, 0x0ef3f3fdU, 0x6dd2d2bfU, + 0x4ccdcd81U, 0x140c0c18U, 0x35131326U, 0x2fececc3U, + 0xe15f5fbeU, 0xa2979735U, 0xcc444488U, 0x3917172eU, + 0x57c4c493U, 0xf2a7a755U, 0x827e7efcU, 0x473d3d7aU, + 0xac6464c8U, 0xe75d5dbaU, 0x2b191932U, 0x957373e6U, + 0xa06060c0U, 0x98818119U, 0xd14f4f9eU, 0x7fdcdca3U, + 0x66222244U, 0x7e2a2a54U, 0xab90903bU, 0x8388880bU, + 0xca46468cU, 0x29eeeec7U, 0xd3b8b86bU, 0x3c141428U, + 0x79dedea7U, 0xe25e5ebcU, 0x1d0b0b16U, 0x76dbdbadU, + 0x3be0e0dbU, 0x56323264U, 0x4e3a3a74U, 0x1e0a0a14U, + 0xdb494992U, 0x0a06060cU, 0x6c242448U, 0xe45c5cb8U, + 0x5dc2c29fU, 0x6ed3d3bdU, 0xefacac43U, 0xa66262c4U, + 0xa8919139U, 0xa4959531U, 0x37e4e4d3U, 0x8b7979f2U, + 0x32e7e7d5U, 0x43c8c88bU, 0x5937376eU, 0xb76d6ddaU, + 0x8c8d8d01U, 0x64d5d5b1U, 0xd24e4e9cU, 0xe0a9a949U, + 0xb46c6cd8U, 0xfa5656acU, 0x07f4f4f3U, 0x25eaeacfU, + 0xaf6565caU, 0x8e7a7af4U, 0xe9aeae47U, 0x18080810U, + 0xd5baba6fU, 0x887878f0U, 0x6f25254aU, 0x722e2e5cU, + 0x241c1c38U, 0xf1a6a657U, 0xc7b4b473U, 0x51c6c697U, + 0x23e8e8cbU, 0x7cdddda1U, 0x9c7474e8U, 0x211f1f3eU, + 0xdd4b4b96U, 0xdcbdbd61U, 0x868b8b0dU, 0x858a8a0fU, + 0x907070e0U, 0x423e3e7cU, 0xc4b5b571U, 0xaa6666ccU, + 0xd8484890U, 0x05030306U, 0x01f6f6f7U, 0x120e0e1cU, + 0xa36161c2U, 0x5f35356aU, 0xf95757aeU, 0xd0b9b969U, + 0x91868617U, 0x58c1c199U, 0x271d1d3aU, 0xb99e9e27U, + 0x38e1e1d9U, 0x13f8f8ebU, 0xb398982bU, 0x33111122U, + 0xbb6969d2U, 0x70d9d9a9U, 0x898e8e07U, 0xa7949433U, + 0xb69b9b2dU, 0x221e1e3cU, 0x92878715U, 0x20e9e9c9U, + 0x49cece87U, 0xff5555aaU, 0x78282850U, 0x7adfdfa5U, + 0x8f8c8c03U, 0xf8a1a159U, 0x80898909U, 0x170d0d1aU, + 0xdabfbf65U, 0x31e6e6d7U, 0xc6424284U, 0xb86868d0U, + 0xc3414182U, 0xb0999929U, 0x772d2d5aU, 0x110f0f1eU, + 0xcbb0b07bU, 0xfc5454a8U, 0xd6bbbb6dU, 0x3a16162cU, +}; + +static const uint32_t S1_T1[256] = { + 0x6363c6a5U, 0x7c7cf884U, 0x7777ee99U, 0x7b7bf68dU, + 0xf2f2ff0dU, 0x6b6bd6bdU, 0x6f6fdeb1U, 0xc5c59154U, + 0x30306050U, 0x01010203U, 0x6767cea9U, 0x2b2b567dU, + 0xfefee719U, 0xd7d7b562U, 0xabab4de6U, 0x7676ec9aU, + 0xcaca8f45U, 0x82821f9dU, 0xc9c98940U, 0x7d7dfa87U, + 0xfafaef15U, 0x5959b2ebU, 0x47478ec9U, 0xf0f0fb0bU, + 0xadad41ecU, 0xd4d4b367U, 0xa2a25ffdU, 0xafaf45eaU, + 0x9c9c23bfU, 0xa4a453f7U, 0x7272e496U, 0xc0c09b5bU, + 0xb7b775c2U, 0xfdfde11cU, 0x93933daeU, 0x26264c6aU, + 0x36366c5aU, 0x3f3f7e41U, 0xf7f7f502U, 0xcccc834fU, + 0x3434685cU, 0xa5a551f4U, 0xe5e5d134U, 0xf1f1f908U, + 0x7171e293U, 0xd8d8ab73U, 0x31316253U, 0x15152a3fU, + 0x0404080cU, 0xc7c79552U, 0x23234665U, 0xc3c39d5eU, + 0x18183028U, 0x969637a1U, 0x05050a0fU, 0x9a9a2fb5U, + 0x07070e09U, 0x12122436U, 0x80801b9bU, 0xe2e2df3dU, + 0xebebcd26U, 0x27274e69U, 0xb2b27fcdU, 0x7575ea9fU, + 0x0909121bU, 0x83831d9eU, 0x2c2c5874U, 0x1a1a342eU, + 0x1b1b362dU, 0x6e6edcb2U, 0x5a5ab4eeU, 0xa0a05bfbU, + 0x5252a4f6U, 0x3b3b764dU, 0xd6d6b761U, 0xb3b37dceU, + 0x2929527bU, 0xe3e3dd3eU, 0x2f2f5e71U, 0x84841397U, + 0x5353a6f5U, 0xd1d1b968U, 0x00000000U, 0xededc12cU, + 0x20204060U, 0xfcfce31fU, 0xb1b179c8U, 0x5b5bb6edU, + 0x6a6ad4beU, 0xcbcb8d46U, 0xbebe67d9U, 0x3939724bU, + 0x4a4a94deU, 0x4c4c98d4U, 0x5858b0e8U, 0xcfcf854aU, + 0xd0d0bb6bU, 0xefefc52aU, 0xaaaa4fe5U, 0xfbfbed16U, + 0x434386c5U, 0x4d4d9ad7U, 0x33336655U, 0x85851194U, + 0x45458acfU, 0xf9f9e910U, 0x02020406U, 0x7f7ffe81U, + 0x5050a0f0U, 0x3c3c7844U, 0x9f9f25baU, 0xa8a84be3U, + 0x5151a2f3U, 0xa3a35dfeU, 0x404080c0U, 0x8f8f058aU, + 0x92923fadU, 0x9d9d21bcU, 0x38387048U, 0xf5f5f104U, + 0xbcbc63dfU, 0xb6b677c1U, 0xdadaaf75U, 0x21214263U, + 0x10102030U, 0xffffe51aU, 0xf3f3fd0eU, 0xd2d2bf6dU, + 0xcdcd814cU, 0x0c0c1814U, 0x13132635U, 0xececc32fU, + 0x5f5fbee1U, 0x979735a2U, 0x444488ccU, 0x17172e39U, + 0xc4c49357U, 0xa7a755f2U, 0x7e7efc82U, 0x3d3d7a47U, + 0x6464c8acU, 0x5d5dbae7U, 0x1919322bU, 0x7373e695U, + 0x6060c0a0U, 0x81811998U, 0x4f4f9ed1U, 0xdcdca37fU, + 0x22224466U, 0x2a2a547eU, 0x90903babU, 0x88880b83U, + 0x46468ccaU, 0xeeeec729U, 0xb8b86bd3U, 0x1414283cU, + 0xdedea779U, 0x5e5ebce2U, 0x0b0b161dU, 0xdbdbad76U, + 0xe0e0db3bU, 0x32326456U, 0x3a3a744eU, 0x0a0a141eU, + 0x494992dbU, 0x06060c0aU, 0x2424486cU, 0x5c5cb8e4U, + 0xc2c29f5dU, 0xd3d3bd6eU, 0xacac43efU, 0x6262c4a6U, + 0x919139a8U, 0x959531a4U, 0xe4e4d337U, 0x7979f28bU, + 0xe7e7d532U, 0xc8c88b43U, 0x37376e59U, 0x6d6ddab7U, + 0x8d8d018cU, 0xd5d5b164U, 0x4e4e9cd2U, 0xa9a949e0U, + 0x6c6cd8b4U, 0x5656acfaU, 0xf4f4f307U, 0xeaeacf25U, + 0x6565caafU, 0x7a7af48eU, 0xaeae47e9U, 0x08081018U, + 0xbaba6fd5U, 0x7878f088U, 0x25254a6fU, 0x2e2e5c72U, + 0x1c1c3824U, 0xa6a657f1U, 0xb4b473c7U, 0xc6c69751U, + 0xe8e8cb23U, 0xdddda17cU, 0x7474e89cU, 0x1f1f3e21U, + 0x4b4b96ddU, 0xbdbd61dcU, 0x8b8b0d86U, 0x8a8a0f85U, + 0x7070e090U, 0x3e3e7c42U, 0xb5b571c4U, 0x6666ccaaU, + 0x484890d8U, 0x03030605U, 0xf6f6f701U, 0x0e0e1c12U, + 0x6161c2a3U, 0x35356a5fU, 0x5757aef9U, 0xb9b969d0U, + 0x86861791U, 0xc1c19958U, 0x1d1d3a27U, 0x9e9e27b9U, + 0xe1e1d938U, 0xf8f8eb13U, 0x98982bb3U, 0x11112233U, + 0x6969d2bbU, 0xd9d9a970U, 0x8e8e0789U, 0x949433a7U, + 0x9b9b2db6U, 0x1e1e3c22U, 0x87871592U, 0xe9e9c920U, + 0xcece8749U, 0x5555aaffU, 0x28285078U, 0xdfdfa57aU, + 0x8c8c038fU, 0xa1a159f8U, 0x89890980U, 0x0d0d1a17U, + 0xbfbf65daU, 0xe6e6d731U, 0x424284c6U, 0x6868d0b8U, + 0x414182c3U, 0x999929b0U, 0x2d2d5a77U, 0x0f0f1e11U, + 0xb0b07bcbU, 0x5454a8fcU, 0xbbbb6dd6U, 0x16162c3aU, +}; + +static const uint32_t S1_T2[256] = { + 0x63c6a563U, 0x7cf8847cU, 0x77ee9977U, 0x7bf68d7bU, + 0xf2ff0df2U, 0x6bd6bd6bU, 0x6fdeb16fU, 0xc59154c5U, + 0x30605030U, 0x01020301U, 0x67cea967U, 0x2b567d2bU, + 0xfee719feU, 0xd7b562d7U, 0xab4de6abU, 0x76ec9a76U, + 0xca8f45caU, 0x821f9d82U, 0xc98940c9U, 0x7dfa877dU, + 0xfaef15faU, 0x59b2eb59U, 0x478ec947U, 0xf0fb0bf0U, + 0xad41ecadU, 0xd4b367d4U, 0xa25ffda2U, 0xaf45eaafU, + 0x9c23bf9cU, 0xa453f7a4U, 0x72e49672U, 0xc09b5bc0U, + 0xb775c2b7U, 0xfde11cfdU, 0x933dae93U, 0x264c6a26U, + 0x366c5a36U, 0x3f7e413fU, 0xf7f502f7U, 0xcc834fccU, + 0x34685c34U, 0xa551f4a5U, 0xe5d134e5U, 0xf1f908f1U, + 0x71e29371U, 0xd8ab73d8U, 0x31625331U, 0x152a3f15U, + 0x04080c04U, 0xc79552c7U, 0x23466523U, 0xc39d5ec3U, + 0x18302818U, 0x9637a196U, 0x050a0f05U, 0x9a2fb59aU, + 0x070e0907U, 0x12243612U, 0x801b9b80U, 0xe2df3de2U, + 0xebcd26ebU, 0x274e6927U, 0xb27fcdb2U, 0x75ea9f75U, + 0x09121b09U, 0x831d9e83U, 0x2c58742cU, 0x1a342e1aU, + 0x1b362d1bU, 0x6edcb26eU, 0x5ab4ee5aU, 0xa05bfba0U, + 0x52a4f652U, 0x3b764d3bU, 0xd6b761d6U, 0xb37dceb3U, + 0x29527b29U, 0xe3dd3ee3U, 0x2f5e712fU, 0x84139784U, + 0x53a6f553U, 0xd1b968d1U, 0x00000000U, 0xedc12cedU, + 0x20406020U, 0xfce31ffcU, 0xb179c8b1U, 0x5bb6ed5bU, + 0x6ad4be6aU, 0xcb8d46cbU, 0xbe67d9beU, 0x39724b39U, + 0x4a94de4aU, 0x4c98d44cU, 0x58b0e858U, 0xcf854acfU, + 0xd0bb6bd0U, 0xefc52aefU, 0xaa4fe5aaU, 0xfbed16fbU, + 0x4386c543U, 0x4d9ad74dU, 0x33665533U, 0x85119485U, + 0x458acf45U, 0xf9e910f9U, 0x02040602U, 0x7ffe817fU, + 0x50a0f050U, 0x3c78443cU, 0x9f25ba9fU, 0xa84be3a8U, + 0x51a2f351U, 0xa35dfea3U, 0x4080c040U, 0x8f058a8fU, + 0x923fad92U, 0x9d21bc9dU, 0x38704838U, 0xf5f104f5U, + 0xbc63dfbcU, 0xb677c1b6U, 0xdaaf75daU, 0x21426321U, + 0x10203010U, 0xffe51affU, 0xf3fd0ef3U, 0xd2bf6dd2U, + 0xcd814ccdU, 0x0c18140cU, 0x13263513U, 0xecc32fecU, + 0x5fbee15fU, 0x9735a297U, 0x4488cc44U, 0x172e3917U, + 0xc49357c4U, 0xa755f2a7U, 0x7efc827eU, 0x3d7a473dU, + 0x64c8ac64U, 0x5dbae75dU, 0x19322b19U, 0x73e69573U, + 0x60c0a060U, 0x81199881U, 0x4f9ed14fU, 0xdca37fdcU, + 0x22446622U, 0x2a547e2aU, 0x903bab90U, 0x880b8388U, + 0x468cca46U, 0xeec729eeU, 0xb86bd3b8U, 0x14283c14U, + 0xdea779deU, 0x5ebce25eU, 0x0b161d0bU, 0xdbad76dbU, + 0xe0db3be0U, 0x32645632U, 0x3a744e3aU, 0x0a141e0aU, + 0x4992db49U, 0x060c0a06U, 0x24486c24U, 0x5cb8e45cU, + 0xc29f5dc2U, 0xd3bd6ed3U, 0xac43efacU, 0x62c4a662U, + 0x9139a891U, 0x9531a495U, 0xe4d337e4U, 0x79f28b79U, + 0xe7d532e7U, 0xc88b43c8U, 0x376e5937U, 0x6ddab76dU, + 0x8d018c8dU, 0xd5b164d5U, 0x4e9cd24eU, 0xa949e0a9U, + 0x6cd8b46cU, 0x56acfa56U, 0xf4f307f4U, 0xeacf25eaU, + 0x65caaf65U, 0x7af48e7aU, 0xae47e9aeU, 0x08101808U, + 0xba6fd5baU, 0x78f08878U, 0x254a6f25U, 0x2e5c722eU, + 0x1c38241cU, 0xa657f1a6U, 0xb473c7b4U, 0xc69751c6U, + 0xe8cb23e8U, 0xdda17cddU, 0x74e89c74U, 0x1f3e211fU, + 0x4b96dd4bU, 0xbd61dcbdU, 0x8b0d868bU, 0x8a0f858aU, + 0x70e09070U, 0x3e7c423eU, 0xb571c4b5U, 0x66ccaa66U, + 0x4890d848U, 0x03060503U, 0xf6f701f6U, 0x0e1c120eU, + 0x61c2a361U, 0x356a5f35U, 0x57aef957U, 0xb969d0b9U, + 0x86179186U, 0xc19958c1U, 0x1d3a271dU, 0x9e27b99eU, + 0xe1d938e1U, 0xf8eb13f8U, 0x982bb398U, 0x11223311U, + 0x69d2bb69U, 0xd9a970d9U, 0x8e07898eU, 0x9433a794U, + 0x9b2db69bU, 0x1e3c221eU, 0x87159287U, 0xe9c920e9U, + 0xce8749ceU, 0x55aaff55U, 0x28507828U, 0xdfa57adfU, + 0x8c038f8cU, 0xa159f8a1U, 0x89098089U, 0x0d1a170dU, + 0xbf65dabfU, 0xe6d731e6U, 0x4284c642U, 0x68d0b868U, + 0x4182c341U, 0x9929b099U, 0x2d5a772dU, 0x0f1e110fU, + 0xb07bcbb0U, 0x54a8fc54U, 0xbb6dd6bbU, 0x162c3a16U, +}; + +static const uint32_t S1_T3[256] = { + 0xc6a56363U, 0xf8847c7cU, 0xee997777U, 0xf68d7b7bU, + 0xff0df2f2U, 0xd6bd6b6bU, 0xdeb16f6fU, 0x9154c5c5U, + 0x60503030U, 0x02030101U, 0xcea96767U, 0x567d2b2bU, + 0xe719fefeU, 0xb562d7d7U, 0x4de6ababU, 0xec9a7676U, + 0x8f45cacaU, 0x1f9d8282U, 0x8940c9c9U, 0xfa877d7dU, + 0xef15fafaU, 0xb2eb5959U, 0x8ec94747U, 0xfb0bf0f0U, + 0x41ecadadU, 0xb367d4d4U, 0x5ffda2a2U, 0x45eaafafU, + 0x23bf9c9cU, 0x53f7a4a4U, 0xe4967272U, 0x9b5bc0c0U, + 0x75c2b7b7U, 0xe11cfdfdU, 0x3dae9393U, 0x4c6a2626U, + 0x6c5a3636U, 0x7e413f3fU, 0xf502f7f7U, 0x834fccccU, + 0x685c3434U, 0x51f4a5a5U, 0xd134e5e5U, 0xf908f1f1U, + 0xe2937171U, 0xab73d8d8U, 0x62533131U, 0x2a3f1515U, + 0x080c0404U, 0x9552c7c7U, 0x46652323U, 0x9d5ec3c3U, + 0x30281818U, 0x37a19696U, 0x0a0f0505U, 0x2fb59a9aU, + 0x0e090707U, 0x24361212U, 0x1b9b8080U, 0xdf3de2e2U, + 0xcd26ebebU, 0x4e692727U, 0x7fcdb2b2U, 0xea9f7575U, + 0x121b0909U, 0x1d9e8383U, 0x58742c2cU, 0x342e1a1aU, + 0x362d1b1bU, 0xdcb26e6eU, 0xb4ee5a5aU, 0x5bfba0a0U, + 0xa4f65252U, 0x764d3b3bU, 0xb761d6d6U, 0x7dceb3b3U, + 0x527b2929U, 0xdd3ee3e3U, 0x5e712f2fU, 0x13978484U, + 0xa6f55353U, 0xb968d1d1U, 0x00000000U, 0xc12cededU, + 0x40602020U, 0xe31ffcfcU, 0x79c8b1b1U, 0xb6ed5b5bU, + 0xd4be6a6aU, 0x8d46cbcbU, 0x67d9bebeU, 0x724b3939U, + 0x94de4a4aU, 0x98d44c4cU, 0xb0e85858U, 0x854acfcfU, + 0xbb6bd0d0U, 0xc52aefefU, 0x4fe5aaaaU, 0xed16fbfbU, + 0x86c54343U, 0x9ad74d4dU, 0x66553333U, 0x11948585U, + 0x8acf4545U, 0xe910f9f9U, 0x04060202U, 0xfe817f7fU, + 0xa0f05050U, 0x78443c3cU, 0x25ba9f9fU, 0x4be3a8a8U, + 0xa2f35151U, 0x5dfea3a3U, 0x80c04040U, 0x058a8f8fU, + 0x3fad9292U, 0x21bc9d9dU, 0x70483838U, 0xf104f5f5U, + 0x63dfbcbcU, 0x77c1b6b6U, 0xaf75dadaU, 0x42632121U, + 0x20301010U, 0xe51affffU, 0xfd0ef3f3U, 0xbf6dd2d2U, + 0x814ccdcdU, 0x18140c0cU, 0x26351313U, 0xc32fececU, + 0xbee15f5fU, 0x35a29797U, 0x88cc4444U, 0x2e391717U, + 0x9357c4c4U, 0x55f2a7a7U, 0xfc827e7eU, 0x7a473d3dU, + 0xc8ac6464U, 0xbae75d5dU, 0x322b1919U, 0xe6957373U, + 0xc0a06060U, 0x19988181U, 0x9ed14f4fU, 0xa37fdcdcU, + 0x44662222U, 0x547e2a2aU, 0x3bab9090U, 0x0b838888U, + 0x8cca4646U, 0xc729eeeeU, 0x6bd3b8b8U, 0x283c1414U, + 0xa779dedeU, 0xbce25e5eU, 0x161d0b0bU, 0xad76dbdbU, + 0xdb3be0e0U, 0x64563232U, 0x744e3a3aU, 0x141e0a0aU, + 0x92db4949U, 0x0c0a0606U, 0x486c2424U, 0xb8e45c5cU, + 0x9f5dc2c2U, 0xbd6ed3d3U, 0x43efacacU, 0xc4a66262U, + 0x39a89191U, 0x31a49595U, 0xd337e4e4U, 0xf28b7979U, + 0xd532e7e7U, 0x8b43c8c8U, 0x6e593737U, 0xdab76d6dU, + 0x018c8d8dU, 0xb164d5d5U, 0x9cd24e4eU, 0x49e0a9a9U, + 0xd8b46c6cU, 0xacfa5656U, 0xf307f4f4U, 0xcf25eaeaU, + 0xcaaf6565U, 0xf48e7a7aU, 0x47e9aeaeU, 0x10180808U, + 0x6fd5babaU, 0xf0887878U, 0x4a6f2525U, 0x5c722e2eU, + 0x38241c1cU, 0x57f1a6a6U, 0x73c7b4b4U, 0x9751c6c6U, + 0xcb23e8e8U, 0xa17cddddU, 0xe89c7474U, 0x3e211f1fU, + 0x96dd4b4bU, 0x61dcbdbdU, 0x0d868b8bU, 0x0f858a8aU, + 0xe0907070U, 0x7c423e3eU, 0x71c4b5b5U, 0xccaa6666U, + 0x90d84848U, 0x06050303U, 0xf701f6f6U, 0x1c120e0eU, + 0xc2a36161U, 0x6a5f3535U, 0xaef95757U, 0x69d0b9b9U, + 0x17918686U, 0x9958c1c1U, 0x3a271d1dU, 0x27b99e9eU, + 0xd938e1e1U, 0xeb13f8f8U, 0x2bb39898U, 0x22331111U, + 0xd2bb6969U, 0xa970d9d9U, 0x07898e8eU, 0x33a79494U, + 0x2db69b9bU, 0x3c221e1eU, 0x15928787U, 0xc920e9e9U, + 0x8749ceceU, 0xaaff5555U, 0x50782828U, 0xa57adfdfU, + 0x038f8c8cU, 0x59f8a1a1U, 0x09808989U, 0x1a170d0dU, + 0x65dabfbfU, 0xd731e6e6U, 0x84c64242U, 0xd0b86868U, + 0x82c34141U, 0x29b09999U, 0x5a772d2dU, 0x1e110f0fU, + 0x7bcbb0b0U, 0xa8fc5454U, 0x6dd6bbbbU, 0x2c3a1616U, +}; + +static const uint32_t S2_T0[256] = { + 0x6f25254aU, 0x6c242448U, 0x957373e6U, 0xa96767ceU, + 0x10d7d7c7U, 0x9baeae35U, 0xe45c5cb8U, 0x50303060U, + 0x85a4a421U, 0x5beeeeb5U, 0xb26e6edcU, 0x34cbcbffU, + 0x877d7dfaU, 0xb6b5b503U, 0xef82826dU, 0x04dbdbdfU, + 0x45e4e4a1U, 0xfb8e8e75U, 0xd8484890U, 0xdb494992U, + 0xd14f4f9eU, 0xe75d5dbaU, 0xbe6a6ad4U, 0x887878f0U, + 0x907070e0U, 0xf1888879U, 0x51e8e8b9U, 0xe15f5fbeU, + 0xe25e5ebcU, 0xe5848461U, 0xaf6565caU, 0x4fe2e2adU, + 0x01d8d8d9U, 0x52e9e9bbU, 0x3dccccf1U, 0x5eededb3U, + 0xc0404080U, 0x712f2f5eU, 0x33111122U, 0x78282850U, + 0xf95757aeU, 0x1fd2d2cdU, 0x9dacac31U, 0x4ce3e3afU, + 0xde4a4a94U, 0x3f15152aU, 0x2d1b1b36U, 0xa2b9b91bU, + 0xbfb2b20dU, 0xe9808069U, 0xe6858563U, 0x83a6a625U, + 0x722e2e5cU, 0x06020204U, 0xc947478eU, 0x7b292952U, + 0x0907070eU, 0xdd4b4b96U, 0x120e0e1cU, 0x2ac1c1ebU, + 0xf35151a2U, 0x97aaaa3dU, 0xf289897bU, 0x15d4d4c1U, + 0x37cacafdU, 0x03010102U, 0xca46468cU, 0xbcb3b30fU, + 0x58efefb7U, 0x0eddddd3U, 0xcc444488U, 0x8d7b7bf6U, + 0x2fc2c2edU, 0x817f7ffeU, 0xabbebe15U, 0x2cc3c3efU, + 0xc89f9f57U, 0x60202040U, 0xd44c4c98U, 0xac6464c8U, + 0xec83836fU, 0x8fa2a22dU, 0xb86868d0U, 0xc6424284U, + 0x35131326U, 0xb5b4b401U, 0xc3414182U, 0x3ecdcdf3U, + 0xa7baba1dU, 0x23c6c6e5U, 0xa4bbbb1fU, 0xb76d6ddaU, + 0xd74d4d9aU, 0x937171e2U, 0x63212142U, 0x75f4f481U, + 0xfe8d8d73U, 0xb9b0b009U, 0x46e5e5a3U, 0xdc93934fU, + 0x6bfefe95U, 0xf88f8f77U, 0x43e6e6a5U, 0x38cfcff7U, + 0xc5434386U, 0xcf45458aU, 0x53313162U, 0x66222244U, + 0x5937376eU, 0x5a36366cU, 0xd3969645U, 0x67fafa9dU, + 0xadbcbc11U, 0x110f0f1eU, 0x18080810U, 0xf65252a4U, + 0x271d1d3aU, 0xff5555aaU, 0x2e1a1a34U, 0x26c5c5e3U, + 0xd24e4e9cU, 0x65232346U, 0xbb6969d2U, 0x8e7a7af4U, + 0xdf92924dU, 0x68ffff97U, 0xed5b5bb6U, 0xee5a5ab4U, + 0x54ebebbfU, 0xc79a9a5dU, 0x241c1c38U, 0x92a9a93bU, + 0x1ad1d1cbU, 0x827e7efcU, 0x170d0d1aU, 0x6dfcfc91U, + 0xf05050a0U, 0xf78a8a7dU, 0xb3b6b605U, 0xa66262c4U, + 0x76f5f583U, 0x1e0a0a14U, 0x61f8f899U, 0x0ddcdcd1U, + 0x05030306U, 0x443c3c78U, 0x140c0c18U, 0x4b393972U, + 0x7af1f18bU, 0xa1b8b819U, 0x7cf3f38fU, 0x473d3d7aU, + 0x7ff2f28dU, 0x16d5d5c3U, 0xd0979747U, 0xaa6666ccU, + 0xea81816bU, 0x56323264U, 0x89a0a029U, 0x00000000U, + 0x0a06060cU, 0x3bcecef5U, 0x73f6f685U, 0x57eaeabdU, + 0xb0b7b707U, 0x3917172eU, 0x70f7f787U, 0xfd8c8c71U, + 0x8b7979f2U, 0x13d6d6c5U, 0x80a7a727U, 0xa8bfbf17U, + 0xf48b8b7fU, 0x413f3f7eU, 0x211f1f3eU, 0xf55353a6U, + 0xa56363c6U, 0x9f7575eaU, 0x5f35356aU, 0x742c2c58U, + 0xa06060c0U, 0x6efdfd93U, 0x6927274eU, 0x1cd3d3cfU, + 0xd5949441U, 0x86a5a523U, 0x847c7cf8U, 0x8aa1a12bU, + 0x0f05050aU, 0xe85858b0U, 0x772d2d5aU, 0xaebdbd13U, + 0x02d9d9dbU, 0x20c7c7e7U, 0x98afaf37U, 0xbd6b6bd6U, + 0xfc5454a8U, 0x1d0b0b16U, 0x49e0e0a9U, 0x48383870U, + 0x0c040408U, 0x31c8c8f9U, 0xce9d9d53U, 0x40e7e7a7U, + 0x3c141428U, 0xbab1b10bU, 0xe0878767U, 0xcd9c9c51U, + 0x08dfdfd7U, 0xb16f6fdeU, 0x62f9f99bU, 0x07dadaddU, + 0x7e2a2a54U, 0x25c4c4e1U, 0xeb5959b2U, 0x3a16162cU, + 0x9c7474e8U, 0xda91914bU, 0x94abab3fU, 0x6a26264cU, + 0xa36161c2U, 0x9a7676ecU, 0x5c343468U, 0x7d2b2b56U, + 0x9eadad33U, 0xc299995bU, 0x64fbfb9fU, 0x967272e4U, + 0x5dececb1U, 0x55333366U, 0x36121224U, 0x0bdeded5U, + 0xc1989859U, 0x4d3b3b76U, 0x29c0c0e9U, 0xc49b9b5fU, + 0x423e3e7cU, 0x28181830U, 0x30101020U, 0x4e3a3a74U, + 0xfa5656acU, 0x4ae1e1abU, 0x997777eeU, 0x32c9c9fbU, + 0x221e1e3cU, 0xcb9e9e55U, 0xd6959543U, 0x8ca3a32fU, + 0xd9909049U, 0x2b191932U, 0x91a8a839U, 0xb46c6cd8U, + 0x1b090912U, 0x19d0d0c9U, 0x79f0f089U, 0xe3868665U, +}; + +static const uint32_t S2_T1[256] = { + 0x25254a6fU, 0x2424486cU, 0x7373e695U, 0x6767cea9U, + 0xd7d7c710U, 0xaeae359bU, 0x5c5cb8e4U, 0x30306050U, + 0xa4a42185U, 0xeeeeb55bU, 0x6e6edcb2U, 0xcbcbff34U, + 0x7d7dfa87U, 0xb5b503b6U, 0x82826defU, 0xdbdbdf04U, + 0xe4e4a145U, 0x8e8e75fbU, 0x484890d8U, 0x494992dbU, + 0x4f4f9ed1U, 0x5d5dbae7U, 0x6a6ad4beU, 0x7878f088U, + 0x7070e090U, 0x888879f1U, 0xe8e8b951U, 0x5f5fbee1U, + 0x5e5ebce2U, 0x848461e5U, 0x6565caafU, 0xe2e2ad4fU, + 0xd8d8d901U, 0xe9e9bb52U, 0xccccf13dU, 0xededb35eU, + 0x404080c0U, 0x2f2f5e71U, 0x11112233U, 0x28285078U, + 0x5757aef9U, 0xd2d2cd1fU, 0xacac319dU, 0xe3e3af4cU, + 0x4a4a94deU, 0x15152a3fU, 0x1b1b362dU, 0xb9b91ba2U, + 0xb2b20dbfU, 0x808069e9U, 0x858563e6U, 0xa6a62583U, + 0x2e2e5c72U, 0x02020406U, 0x47478ec9U, 0x2929527bU, + 0x07070e09U, 0x4b4b96ddU, 0x0e0e1c12U, 0xc1c1eb2aU, + 0x5151a2f3U, 0xaaaa3d97U, 0x89897bf2U, 0xd4d4c115U, + 0xcacafd37U, 0x01010203U, 0x46468ccaU, 0xb3b30fbcU, + 0xefefb758U, 0xddddd30eU, 0x444488ccU, 0x7b7bf68dU, + 0xc2c2ed2fU, 0x7f7ffe81U, 0xbebe15abU, 0xc3c3ef2cU, + 0x9f9f57c8U, 0x20204060U, 0x4c4c98d4U, 0x6464c8acU, + 0x83836fecU, 0xa2a22d8fU, 0x6868d0b8U, 0x424284c6U, + 0x13132635U, 0xb4b401b5U, 0x414182c3U, 0xcdcdf33eU, + 0xbaba1da7U, 0xc6c6e523U, 0xbbbb1fa4U, 0x6d6ddab7U, + 0x4d4d9ad7U, 0x7171e293U, 0x21214263U, 0xf4f48175U, + 0x8d8d73feU, 0xb0b009b9U, 0xe5e5a346U, 0x93934fdcU, + 0xfefe956bU, 0x8f8f77f8U, 0xe6e6a543U, 0xcfcff738U, + 0x434386c5U, 0x45458acfU, 0x31316253U, 0x22224466U, + 0x37376e59U, 0x36366c5aU, 0x969645d3U, 0xfafa9d67U, + 0xbcbc11adU, 0x0f0f1e11U, 0x08081018U, 0x5252a4f6U, + 0x1d1d3a27U, 0x5555aaffU, 0x1a1a342eU, 0xc5c5e326U, + 0x4e4e9cd2U, 0x23234665U, 0x6969d2bbU, 0x7a7af48eU, + 0x92924ddfU, 0xffff9768U, 0x5b5bb6edU, 0x5a5ab4eeU, + 0xebebbf54U, 0x9a9a5dc7U, 0x1c1c3824U, 0xa9a93b92U, + 0xd1d1cb1aU, 0x7e7efc82U, 0x0d0d1a17U, 0xfcfc916dU, + 0x5050a0f0U, 0x8a8a7df7U, 0xb6b605b3U, 0x6262c4a6U, + 0xf5f58376U, 0x0a0a141eU, 0xf8f89961U, 0xdcdcd10dU, + 0x03030605U, 0x3c3c7844U, 0x0c0c1814U, 0x3939724bU, + 0xf1f18b7aU, 0xb8b819a1U, 0xf3f38f7cU, 0x3d3d7a47U, + 0xf2f28d7fU, 0xd5d5c316U, 0x979747d0U, 0x6666ccaaU, + 0x81816beaU, 0x32326456U, 0xa0a02989U, 0x00000000U, + 0x06060c0aU, 0xcecef53bU, 0xf6f68573U, 0xeaeabd57U, + 0xb7b707b0U, 0x17172e39U, 0xf7f78770U, 0x8c8c71fdU, + 0x7979f28bU, 0xd6d6c513U, 0xa7a72780U, 0xbfbf17a8U, + 0x8b8b7ff4U, 0x3f3f7e41U, 0x1f1f3e21U, 0x5353a6f5U, + 0x6363c6a5U, 0x7575ea9fU, 0x35356a5fU, 0x2c2c5874U, + 0x6060c0a0U, 0xfdfd936eU, 0x27274e69U, 0xd3d3cf1cU, + 0x949441d5U, 0xa5a52386U, 0x7c7cf884U, 0xa1a12b8aU, + 0x05050a0fU, 0x5858b0e8U, 0x2d2d5a77U, 0xbdbd13aeU, + 0xd9d9db02U, 0xc7c7e720U, 0xafaf3798U, 0x6b6bd6bdU, + 0x5454a8fcU, 0x0b0b161dU, 0xe0e0a949U, 0x38387048U, + 0x0404080cU, 0xc8c8f931U, 0x9d9d53ceU, 0xe7e7a740U, + 0x1414283cU, 0xb1b10bbaU, 0x878767e0U, 0x9c9c51cdU, + 0xdfdfd708U, 0x6f6fdeb1U, 0xf9f99b62U, 0xdadadd07U, + 0x2a2a547eU, 0xc4c4e125U, 0x5959b2ebU, 0x16162c3aU, + 0x7474e89cU, 0x91914bdaU, 0xabab3f94U, 0x26264c6aU, + 0x6161c2a3U, 0x7676ec9aU, 0x3434685cU, 0x2b2b567dU, + 0xadad339eU, 0x99995bc2U, 0xfbfb9f64U, 0x7272e496U, + 0xececb15dU, 0x33336655U, 0x12122436U, 0xdeded50bU, + 0x989859c1U, 0x3b3b764dU, 0xc0c0e929U, 0x9b9b5fc4U, + 0x3e3e7c42U, 0x18183028U, 0x10102030U, 0x3a3a744eU, + 0x5656acfaU, 0xe1e1ab4aU, 0x7777ee99U, 0xc9c9fb32U, + 0x1e1e3c22U, 0x9e9e55cbU, 0x959543d6U, 0xa3a32f8cU, + 0x909049d9U, 0x1919322bU, 0xa8a83991U, 0x6c6cd8b4U, + 0x0909121bU, 0xd0d0c919U, 0xf0f08979U, 0x868665e3U, +}; + +static const uint32_t S2_T2[256] = { + 0x254a6f25U, 0x24486c24U, 0x73e69573U, 0x67cea967U, + 0xd7c710d7U, 0xae359baeU, 0x5cb8e45cU, 0x30605030U, + 0xa42185a4U, 0xeeb55beeU, 0x6edcb26eU, 0xcbff34cbU, + 0x7dfa877dU, 0xb503b6b5U, 0x826def82U, 0xdbdf04dbU, + 0xe4a145e4U, 0x8e75fb8eU, 0x4890d848U, 0x4992db49U, + 0x4f9ed14fU, 0x5dbae75dU, 0x6ad4be6aU, 0x78f08878U, + 0x70e09070U, 0x8879f188U, 0xe8b951e8U, 0x5fbee15fU, + 0x5ebce25eU, 0x8461e584U, 0x65caaf65U, 0xe2ad4fe2U, + 0xd8d901d8U, 0xe9bb52e9U, 0xccf13dccU, 0xedb35eedU, + 0x4080c040U, 0x2f5e712fU, 0x11223311U, 0x28507828U, + 0x57aef957U, 0xd2cd1fd2U, 0xac319dacU, 0xe3af4ce3U, + 0x4a94de4aU, 0x152a3f15U, 0x1b362d1bU, 0xb91ba2b9U, + 0xb20dbfb2U, 0x8069e980U, 0x8563e685U, 0xa62583a6U, + 0x2e5c722eU, 0x02040602U, 0x478ec947U, 0x29527b29U, + 0x070e0907U, 0x4b96dd4bU, 0x0e1c120eU, 0xc1eb2ac1U, + 0x51a2f351U, 0xaa3d97aaU, 0x897bf289U, 0xd4c115d4U, + 0xcafd37caU, 0x01020301U, 0x468cca46U, 0xb30fbcb3U, + 0xefb758efU, 0xddd30eddU, 0x4488cc44U, 0x7bf68d7bU, + 0xc2ed2fc2U, 0x7ffe817fU, 0xbe15abbeU, 0xc3ef2cc3U, + 0x9f57c89fU, 0x20406020U, 0x4c98d44cU, 0x64c8ac64U, + 0x836fec83U, 0xa22d8fa2U, 0x68d0b868U, 0x4284c642U, + 0x13263513U, 0xb401b5b4U, 0x4182c341U, 0xcdf33ecdU, + 0xba1da7baU, 0xc6e523c6U, 0xbb1fa4bbU, 0x6ddab76dU, + 0x4d9ad74dU, 0x71e29371U, 0x21426321U, 0xf48175f4U, + 0x8d73fe8dU, 0xb009b9b0U, 0xe5a346e5U, 0x934fdc93U, + 0xfe956bfeU, 0x8f77f88fU, 0xe6a543e6U, 0xcff738cfU, + 0x4386c543U, 0x458acf45U, 0x31625331U, 0x22446622U, + 0x376e5937U, 0x366c5a36U, 0x9645d396U, 0xfa9d67faU, + 0xbc11adbcU, 0x0f1e110fU, 0x08101808U, 0x52a4f652U, + 0x1d3a271dU, 0x55aaff55U, 0x1a342e1aU, 0xc5e326c5U, + 0x4e9cd24eU, 0x23466523U, 0x69d2bb69U, 0x7af48e7aU, + 0x924ddf92U, 0xff9768ffU, 0x5bb6ed5bU, 0x5ab4ee5aU, + 0xebbf54ebU, 0x9a5dc79aU, 0x1c38241cU, 0xa93b92a9U, + 0xd1cb1ad1U, 0x7efc827eU, 0x0d1a170dU, 0xfc916dfcU, + 0x50a0f050U, 0x8a7df78aU, 0xb605b3b6U, 0x62c4a662U, + 0xf58376f5U, 0x0a141e0aU, 0xf89961f8U, 0xdcd10ddcU, + 0x03060503U, 0x3c78443cU, 0x0c18140cU, 0x39724b39U, + 0xf18b7af1U, 0xb819a1b8U, 0xf38f7cf3U, 0x3d7a473dU, + 0xf28d7ff2U, 0xd5c316d5U, 0x9747d097U, 0x66ccaa66U, + 0x816bea81U, 0x32645632U, 0xa02989a0U, 0x00000000U, + 0x060c0a06U, 0xcef53bceU, 0xf68573f6U, 0xeabd57eaU, + 0xb707b0b7U, 0x172e3917U, 0xf78770f7U, 0x8c71fd8cU, + 0x79f28b79U, 0xd6c513d6U, 0xa72780a7U, 0xbf17a8bfU, + 0x8b7ff48bU, 0x3f7e413fU, 0x1f3e211fU, 0x53a6f553U, + 0x63c6a563U, 0x75ea9f75U, 0x356a5f35U, 0x2c58742cU, + 0x60c0a060U, 0xfd936efdU, 0x274e6927U, 0xd3cf1cd3U, + 0x9441d594U, 0xa52386a5U, 0x7cf8847cU, 0xa12b8aa1U, + 0x050a0f05U, 0x58b0e858U, 0x2d5a772dU, 0xbd13aebdU, + 0xd9db02d9U, 0xc7e720c7U, 0xaf3798afU, 0x6bd6bd6bU, + 0x54a8fc54U, 0x0b161d0bU, 0xe0a949e0U, 0x38704838U, + 0x04080c04U, 0xc8f931c8U, 0x9d53ce9dU, 0xe7a740e7U, + 0x14283c14U, 0xb10bbab1U, 0x8767e087U, 0x9c51cd9cU, + 0xdfd708dfU, 0x6fdeb16fU, 0xf99b62f9U, 0xdadd07daU, + 0x2a547e2aU, 0xc4e125c4U, 0x59b2eb59U, 0x162c3a16U, + 0x74e89c74U, 0x914bda91U, 0xab3f94abU, 0x264c6a26U, + 0x61c2a361U, 0x76ec9a76U, 0x34685c34U, 0x2b567d2bU, + 0xad339eadU, 0x995bc299U, 0xfb9f64fbU, 0x72e49672U, + 0xecb15decU, 0x33665533U, 0x12243612U, 0xded50bdeU, + 0x9859c198U, 0x3b764d3bU, 0xc0e929c0U, 0x9b5fc49bU, + 0x3e7c423eU, 0x18302818U, 0x10203010U, 0x3a744e3aU, + 0x56acfa56U, 0xe1ab4ae1U, 0x77ee9977U, 0xc9fb32c9U, + 0x1e3c221eU, 0x9e55cb9eU, 0x9543d695U, 0xa32f8ca3U, + 0x9049d990U, 0x19322b19U, 0xa83991a8U, 0x6cd8b46cU, + 0x09121b09U, 0xd0c919d0U, 0xf08979f0U, 0x8665e386U, +}; + +static const uint32_t S2_T3[256] = { + 0x4a6f2525U, 0x486c2424U, 0xe6957373U, 0xcea96767U, + 0xc710d7d7U, 0x359baeaeU, 0xb8e45c5cU, 0x60503030U, + 0x2185a4a4U, 0xb55beeeeU, 0xdcb26e6eU, 0xff34cbcbU, + 0xfa877d7dU, 0x03b6b5b5U, 0x6def8282U, 0xdf04dbdbU, + 0xa145e4e4U, 0x75fb8e8eU, 0x90d84848U, 0x92db4949U, + 0x9ed14f4fU, 0xbae75d5dU, 0xd4be6a6aU, 0xf0887878U, + 0xe0907070U, 0x79f18888U, 0xb951e8e8U, 0xbee15f5fU, + 0xbce25e5eU, 0x61e58484U, 0xcaaf6565U, 0xad4fe2e2U, + 0xd901d8d8U, 0xbb52e9e9U, 0xf13dccccU, 0xb35eededU, + 0x80c04040U, 0x5e712f2fU, 0x22331111U, 0x50782828U, + 0xaef95757U, 0xcd1fd2d2U, 0x319dacacU, 0xaf4ce3e3U, + 0x94de4a4aU, 0x2a3f1515U, 0x362d1b1bU, 0x1ba2b9b9U, + 0x0dbfb2b2U, 0x69e98080U, 0x63e68585U, 0x2583a6a6U, + 0x5c722e2eU, 0x04060202U, 0x8ec94747U, 0x527b2929U, + 0x0e090707U, 0x96dd4b4bU, 0x1c120e0eU, 0xeb2ac1c1U, + 0xa2f35151U, 0x3d97aaaaU, 0x7bf28989U, 0xc115d4d4U, + 0xfd37cacaU, 0x02030101U, 0x8cca4646U, 0x0fbcb3b3U, + 0xb758efefU, 0xd30eddddU, 0x88cc4444U, 0xf68d7b7bU, + 0xed2fc2c2U, 0xfe817f7fU, 0x15abbebeU, 0xef2cc3c3U, + 0x57c89f9fU, 0x40602020U, 0x98d44c4cU, 0xc8ac6464U, + 0x6fec8383U, 0x2d8fa2a2U, 0xd0b86868U, 0x84c64242U, + 0x26351313U, 0x01b5b4b4U, 0x82c34141U, 0xf33ecdcdU, + 0x1da7babaU, 0xe523c6c6U, 0x1fa4bbbbU, 0xdab76d6dU, + 0x9ad74d4dU, 0xe2937171U, 0x42632121U, 0x8175f4f4U, + 0x73fe8d8dU, 0x09b9b0b0U, 0xa346e5e5U, 0x4fdc9393U, + 0x956bfefeU, 0x77f88f8fU, 0xa543e6e6U, 0xf738cfcfU, + 0x86c54343U, 0x8acf4545U, 0x62533131U, 0x44662222U, + 0x6e593737U, 0x6c5a3636U, 0x45d39696U, 0x9d67fafaU, + 0x11adbcbcU, 0x1e110f0fU, 0x10180808U, 0xa4f65252U, + 0x3a271d1dU, 0xaaff5555U, 0x342e1a1aU, 0xe326c5c5U, + 0x9cd24e4eU, 0x46652323U, 0xd2bb6969U, 0xf48e7a7aU, + 0x4ddf9292U, 0x9768ffffU, 0xb6ed5b5bU, 0xb4ee5a5aU, + 0xbf54ebebU, 0x5dc79a9aU, 0x38241c1cU, 0x3b92a9a9U, + 0xcb1ad1d1U, 0xfc827e7eU, 0x1a170d0dU, 0x916dfcfcU, + 0xa0f05050U, 0x7df78a8aU, 0x05b3b6b6U, 0xc4a66262U, + 0x8376f5f5U, 0x141e0a0aU, 0x9961f8f8U, 0xd10ddcdcU, + 0x06050303U, 0x78443c3cU, 0x18140c0cU, 0x724b3939U, + 0x8b7af1f1U, 0x19a1b8b8U, 0x8f7cf3f3U, 0x7a473d3dU, + 0x8d7ff2f2U, 0xc316d5d5U, 0x47d09797U, 0xccaa6666U, + 0x6bea8181U, 0x64563232U, 0x2989a0a0U, 0x00000000U, + 0x0c0a0606U, 0xf53bceceU, 0x8573f6f6U, 0xbd57eaeaU, + 0x07b0b7b7U, 0x2e391717U, 0x8770f7f7U, 0x71fd8c8cU, + 0xf28b7979U, 0xc513d6d6U, 0x2780a7a7U, 0x17a8bfbfU, + 0x7ff48b8bU, 0x7e413f3fU, 0x3e211f1fU, 0xa6f55353U, + 0xc6a56363U, 0xea9f7575U, 0x6a5f3535U, 0x58742c2cU, + 0xc0a06060U, 0x936efdfdU, 0x4e692727U, 0xcf1cd3d3U, + 0x41d59494U, 0x2386a5a5U, 0xf8847c7cU, 0x2b8aa1a1U, + 0x0a0f0505U, 0xb0e85858U, 0x5a772d2dU, 0x13aebdbdU, + 0xdb02d9d9U, 0xe720c7c7U, 0x3798afafU, 0xd6bd6b6bU, + 0xa8fc5454U, 0x161d0b0bU, 0xa949e0e0U, 0x70483838U, + 0x080c0404U, 0xf931c8c8U, 0x53ce9d9dU, 0xa740e7e7U, + 0x283c1414U, 0x0bbab1b1U, 0x67e08787U, 0x51cd9c9cU, + 0xd708dfdfU, 0xdeb16f6fU, 0x9b62f9f9U, 0xdd07dadaU, + 0x547e2a2aU, 0xe125c4c4U, 0xb2eb5959U, 0x2c3a1616U, + 0xe89c7474U, 0x4bda9191U, 0x3f94ababU, 0x4c6a2626U, + 0xc2a36161U, 0xec9a7676U, 0x685c3434U, 0x567d2b2bU, + 0x339eadadU, 0x5bc29999U, 0x9f64fbfbU, 0xe4967272U, + 0xb15dececU, 0x66553333U, 0x24361212U, 0xd50bdedeU, + 0x59c19898U, 0x764d3b3bU, 0xe929c0c0U, 0x5fc49b9bU, + 0x7c423e3eU, 0x30281818U, 0x20301010U, 0x744e3a3aU, + 0xacfa5656U, 0xab4ae1e1U, 0xee997777U, 0xfb32c9c9U, + 0x3c221e1eU, 0x55cb9e9eU, 0x43d69595U, 0x2f8ca3a3U, + 0x49d99090U, 0x322b1919U, 0x3991a8a8U, 0xd8b46c6cU, + 0x121b0909U, 0xc919d0d0U, 0x8979f0f0U, 0x65e38686U, +}; + +static const uint32_t MULalpha[256] = { + 0x00000000U, 0xE19FCF13U, 0x6B973726U, 0x8A08F835U, + 0xD6876E4CU, 0x3718A15FU, 0xBD10596AU, 0x5C8F9679U, + 0x05A7DC98U, 0xE438138BU, 0x6E30EBBEU, 0x8FAF24ADU, + 0xD320B2D4U, 0x32BF7DC7U, 0xB8B785F2U, 0x59284AE1U, + 0x0AE71199U, 0xEB78DE8AU, 0x617026BFU, 0x80EFE9ACU, + 0xDC607FD5U, 0x3DFFB0C6U, 0xB7F748F3U, 0x566887E0U, + 0x0F40CD01U, 0xEEDF0212U, 0x64D7FA27U, 0x85483534U, + 0xD9C7A34DU, 0x38586C5EU, 0xB250946BU, 0x53CF5B78U, + 0x1467229BU, 0xF5F8ED88U, 0x7FF015BDU, 0x9E6FDAAEU, + 0xC2E04CD7U, 0x237F83C4U, 0xA9777BF1U, 0x48E8B4E2U, + 0x11C0FE03U, 0xF05F3110U, 0x7A57C925U, 0x9BC80636U, + 0xC747904FU, 0x26D85F5CU, 0xACD0A769U, 0x4D4F687AU, + 0x1E803302U, 0xFF1FFC11U, 0x75170424U, 0x9488CB37U, + 0xC8075D4EU, 0x2998925DU, 0xA3906A68U, 0x420FA57BU, + 0x1B27EF9AU, 0xFAB82089U, 0x70B0D8BCU, 0x912F17AFU, + 0xCDA081D6U, 0x2C3F4EC5U, 0xA637B6F0U, 0x47A879E3U, + 0x28CE449FU, 0xC9518B8CU, 0x435973B9U, 0xA2C6BCAAU, + 0xFE492AD3U, 0x1FD6E5C0U, 0x95DE1DF5U, 0x7441D2E6U, + 0x2D699807U, 0xCCF65714U, 0x46FEAF21U, 0xA7616032U, + 0xFBEEF64BU, 0x1A713958U, 0x9079C16DU, 0x71E60E7EU, + 0x22295506U, 0xC3B69A15U, 0x49BE6220U, 0xA821AD33U, + 0xF4AE3B4AU, 0x1531F459U, 0x9F390C6CU, 0x7EA6C37FU, + 0x278E899EU, 0xC611468DU, 0x4C19BEB8U, 0xAD8671ABU, + 0xF109E7D2U, 0x109628C1U, 0x9A9ED0F4U, 0x7B011FE7U, + 0x3CA96604U, 0xDD36A917U, 0x573E5122U, 0xB6A19E31U, + 0xEA2E0848U, 0x0BB1C75BU, 0x81B93F6EU, 0x6026F07DU, + 0x390EBA9CU, 0xD891758FU, 0x52998DBAU, 0xB30642A9U, + 0xEF89D4D0U, 0x0E161BC3U, 0x841EE3F6U, 0x65812CE5U, + 0x364E779DU, 0xD7D1B88EU, 0x5DD940BBU, 0xBC468FA8U, + 0xE0C919D1U, 0x0156D6C2U, 0x8B5E2EF7U, 0x6AC1E1E4U, + 0x33E9AB05U, 0xD2766416U, 0x587E9C23U, 0xB9E15330U, + 0xE56EC549U, 0x04F10A5AU, 0x8EF9F26FU, 0x6F663D7CU, + 0x50358897U, 0xB1AA4784U, 0x3BA2BFB1U, 0xDA3D70A2U, + 0x86B2E6DBU, 0x672D29C8U, 0xED25D1FDU, 0x0CBA1EEEU, + 0x5592540FU, 0xB40D9B1CU, 0x3E056329U, 0xDF9AAC3AU, + 0x83153A43U, 0x628AF550U, 0xE8820D65U, 0x091DC276U, + 0x5AD2990EU, 0xBB4D561DU, 0x3145AE28U, 0xD0DA613BU, + 0x8C55F742U, 0x6DCA3851U, 0xE7C2C064U, 0x065D0F77U, + 0x5F754596U, 0xBEEA8A85U, 0x34E272B0U, 0xD57DBDA3U, + 0x89F22BDAU, 0x686DE4C9U, 0xE2651CFCU, 0x03FAD3EFU, + 0x4452AA0CU, 0xA5CD651FU, 0x2FC59D2AU, 0xCE5A5239U, + 0x92D5C440U, 0x734A0B53U, 0xF942F366U, 0x18DD3C75U, + 0x41F57694U, 0xA06AB987U, 0x2A6241B2U, 0xCBFD8EA1U, + 0x977218D8U, 0x76EDD7CBU, 0xFCE52FFEU, 0x1D7AE0EDU, + 0x4EB5BB95U, 0xAF2A7486U, 0x25228CB3U, 0xC4BD43A0U, + 0x9832D5D9U, 0x79AD1ACAU, 0xF3A5E2FFU, 0x123A2DECU, + 0x4B12670DU, 0xAA8DA81EU, 0x2085502BU, 0xC11A9F38U, + 0x9D950941U, 0x7C0AC652U, 0xF6023E67U, 0x179DF174U, + 0x78FBCC08U, 0x9964031BU, 0x136CFB2EU, 0xF2F3343DU, + 0xAE7CA244U, 0x4FE36D57U, 0xC5EB9562U, 0x24745A71U, + 0x7D5C1090U, 0x9CC3DF83U, 0x16CB27B6U, 0xF754E8A5U, + 0xABDB7EDCU, 0x4A44B1CFU, 0xC04C49FAU, 0x21D386E9U, + 0x721CDD91U, 0x93831282U, 0x198BEAB7U, 0xF81425A4U, + 0xA49BB3DDU, 0x45047CCEU, 0xCF0C84FBU, 0x2E934BE8U, + 0x77BB0109U, 0x9624CE1AU, 0x1C2C362FU, 0xFDB3F93CU, + 0xA13C6F45U, 0x40A3A056U, 0xCAAB5863U, 0x2B349770U, + 0x6C9CEE93U, 0x8D032180U, 0x070BD9B5U, 0xE69416A6U, + 0xBA1B80DFU, 0x5B844FCCU, 0xD18CB7F9U, 0x301378EAU, + 0x693B320BU, 0x88A4FD18U, 0x02AC052DU, 0xE333CA3EU, + 0xBFBC5C47U, 0x5E239354U, 0xD42B6B61U, 0x35B4A472U, + 0x667BFF0AU, 0x87E43019U, 0x0DECC82CU, 0xEC73073FU, + 0xB0FC9146U, 0x51635E55U, 0xDB6BA660U, 0x3AF46973U, + 0x63DC2392U, 0x8243EC81U, 0x084B14B4U, 0xE9D4DBA7U, + 0xB55B4DDEU, 0x54C482CDU, 0xDECC7AF8U, 0x3F53B5EBU, +}; + +static const uint32_t DIValpha[256] = { + 0x00000000U, 0x180F40CDU, 0x301E8033U, 0x2811C0FEU, + 0x603CA966U, 0x7833E9ABU, 0x50222955U, 0x482D6998U, + 0xC078FBCCU, 0xD877BB01U, 0xF0667BFFU, 0xE8693B32U, + 0xA04452AAU, 0xB84B1267U, 0x905AD299U, 0x88559254U, + 0x29F05F31U, 0x31FF1FFCU, 0x19EEDF02U, 0x01E19FCFU, + 0x49CCF657U, 0x51C3B69AU, 0x79D27664U, 0x61DD36A9U, + 0xE988A4FDU, 0xF187E430U, 0xD99624CEU, 0xC1996403U, + 0x89B40D9BU, 0x91BB4D56U, 0xB9AA8DA8U, 0xA1A5CD65U, + 0x5249BE62U, 0x4A46FEAFU, 0x62573E51U, 0x7A587E9CU, + 0x32751704U, 0x2A7A57C9U, 0x026B9737U, 0x1A64D7FAU, + 0x923145AEU, 0x8A3E0563U, 0xA22FC59DU, 0xBA208550U, + 0xF20DECC8U, 0xEA02AC05U, 0xC2136CFBU, 0xDA1C2C36U, + 0x7BB9E153U, 0x63B6A19EU, 0x4BA76160U, 0x53A821ADU, + 0x1B854835U, 0x038A08F8U, 0x2B9BC806U, 0x339488CBU, + 0xBBC11A9FU, 0xA3CE5A52U, 0x8BDF9AACU, 0x93D0DA61U, + 0xDBFDB3F9U, 0xC3F2F334U, 0xEBE333CAU, 0xF3EC7307U, + 0xA492D5C4U, 0xBC9D9509U, 0x948C55F7U, 0x8C83153AU, + 0xC4AE7CA2U, 0xDCA13C6FU, 0xF4B0FC91U, 0xECBFBC5CU, + 0x64EA2E08U, 0x7CE56EC5U, 0x54F4AE3BU, 0x4CFBEEF6U, + 0x04D6876EU, 0x1CD9C7A3U, 0x34C8075DU, 0x2CC74790U, + 0x8D628AF5U, 0x956DCA38U, 0xBD7C0AC6U, 0xA5734A0BU, + 0xED5E2393U, 0xF551635EU, 0xDD40A3A0U, 0xC54FE36DU, + 0x4D1A7139U, 0x551531F4U, 0x7D04F10AU, 0x650BB1C7U, + 0x2D26D85FU, 0x35299892U, 0x1D38586CU, 0x053718A1U, + 0xF6DB6BA6U, 0xEED42B6BU, 0xC6C5EB95U, 0xDECAAB58U, + 0x96E7C2C0U, 0x8EE8820DU, 0xA6F942F3U, 0xBEF6023EU, + 0x36A3906AU, 0x2EACD0A7U, 0x06BD1059U, 0x1EB25094U, + 0x569F390CU, 0x4E9079C1U, 0x6681B93FU, 0x7E8EF9F2U, + 0xDF2B3497U, 0xC724745AU, 0xEF35B4A4U, 0xF73AF469U, + 0xBF179DF1U, 0xA718DD3CU, 0x8F091DC2U, 0x97065D0FU, + 0x1F53CF5BU, 0x075C8F96U, 0x2F4D4F68U, 0x37420FA5U, + 0x7F6F663DU, 0x676026F0U, 0x4F71E60EU, 0x577EA6C3U, + 0xE18D0321U, 0xF98243ECU, 0xD1938312U, 0xC99CC3DFU, + 0x81B1AA47U, 0x99BEEA8AU, 0xB1AF2A74U, 0xA9A06AB9U, + 0x21F5F8EDU, 0x39FAB820U, 0x11EB78DEU, 0x09E43813U, + 0x41C9518BU, 0x59C61146U, 0x71D7D1B8U, 0x69D89175U, + 0xC87D5C10U, 0xD0721CDDU, 0xF863DC23U, 0xE06C9CEEU, + 0xA841F576U, 0xB04EB5BBU, 0x985F7545U, 0x80503588U, + 0x0805A7DCU, 0x100AE711U, 0x381B27EFU, 0x20146722U, + 0x68390EBAU, 0x70364E77U, 0x58278E89U, 0x4028CE44U, + 0xB3C4BD43U, 0xABCBFD8EU, 0x83DA3D70U, 0x9BD57DBDU, + 0xD3F81425U, 0xCBF754E8U, 0xE3E69416U, 0xFBE9D4DBU, + 0x73BC468FU, 0x6BB30642U, 0x43A2C6BCU, 0x5BAD8671U, + 0x1380EFE9U, 0x0B8FAF24U, 0x239E6FDAU, 0x3B912F17U, + 0x9A34E272U, 0x823BA2BFU, 0xAA2A6241U, 0xB225228CU, + 0xFA084B14U, 0xE2070BD9U, 0xCA16CB27U, 0xD2198BEAU, + 0x5A4C19BEU, 0x42435973U, 0x6A52998DU, 0x725DD940U, + 0x3A70B0D8U, 0x227FF015U, 0x0A6E30EBU, 0x12617026U, + 0x451FD6E5U, 0x5D109628U, 0x750156D6U, 0x6D0E161BU, + 0x25237F83U, 0x3D2C3F4EU, 0x153DFFB0U, 0x0D32BF7DU, + 0x85672D29U, 0x9D686DE4U, 0xB579AD1AU, 0xAD76EDD7U, + 0xE55B844FU, 0xFD54C482U, 0xD545047CU, 0xCD4A44B1U, + 0x6CEF89D4U, 0x74E0C919U, 0x5CF109E7U, 0x44FE492AU, + 0x0CD320B2U, 0x14DC607FU, 0x3CCDA081U, 0x24C2E04CU, + 0xAC977218U, 0xB49832D5U, 0x9C89F22BU, 0x8486B2E6U, + 0xCCABDB7EU, 0xD4A49BB3U, 0xFCB55B4DU, 0xE4BA1B80U, + 0x17566887U, 0x0F59284AU, 0x2748E8B4U, 0x3F47A879U, + 0x776AC1E1U, 0x6F65812CU, 0x477441D2U, 0x5F7B011FU, + 0xD72E934BU, 0xCF21D386U, 0xE7301378U, 0xFF3F53B5U, + 0xB7123A2DU, 0xAF1D7AE0U, 0x870CBA1EU, 0x9F03FAD3U, + 0x3EA637B6U, 0x26A9777BU, 0x0EB8B785U, 0x16B7F748U, + 0x5E9A9ED0U, 0x4695DE1DU, 0x6E841EE3U, 0x768B5E2EU, + 0xFEDECC7AU, 0xE6D18CB7U, 0xCEC04C49U, 0xD6CF0C84U, + 0x9EE2651CU, 0x86ED25D1U, 0xAEFCE52FU, 0xB6F3A5E2U, +}; + +/* Primitives */ +/* Get the i most significant byte out of a 32 bit word */ +#define BYTE32(word, i) (uint8_t) ((word >> 8*(3-i)) & 0xff) + +#if 1 /* modified by acetcom */ +uint32_t +snow_S1(uint32_t in); +uint32_t +snow_S2(uint32_t in); +void +lfsr_init(uint32_t f, SNOW_CTX *ctx); +void +lfsr_keystream(SNOW_CTX *ctx); +uint32_t +clock_fsm(SNOW_CTX *ctx); +void +snow_init_lfsr_fsm(struct snow_key_st key, SNOW_CTX *ctx); +#endif + +uint32_t +snow_S1(uint32_t in) +{ + return S1_T0[BYTE32(in, 3)] ^ S1_T1[BYTE32(in, 2)] ^ + S1_T2[BYTE32(in, 1)] ^ S1_T3[BYTE32(in, 0)]; +} + +uint32_t +snow_S2(uint32_t in) +{ + return S2_T0[BYTE32(in, 3)] ^ S2_T1[BYTE32(in, 2)] ^ + S2_T2[BYTE32(in, 1)] ^ S2_T3[BYTE32(in, 0)]; +} + +/* Clocking operations */ +void +lfsr_init(uint32_t f, SNOW_CTX *ctx) +{ + uint32_t v = ( + ((ctx->lfsr[0] << 8) & 0xffffff00) ^ + MULalpha[BYTE32(ctx->lfsr[0], 0)] ^ + ctx->lfsr[2] ^ + ((ctx->lfsr[11] >> 8) & 0x00ffffff) ^ + DIValpha[BYTE32(ctx->lfsr[11], 3)] ^ + f + ); + ctx->lfsr[0] = ctx->lfsr[1]; + ctx->lfsr[1] = ctx->lfsr[2]; + ctx->lfsr[2] = ctx->lfsr[3]; + ctx->lfsr[3] = ctx->lfsr[4]; + ctx->lfsr[4] = ctx->lfsr[5]; + ctx->lfsr[5] = ctx->lfsr[6]; + ctx->lfsr[6] = ctx->lfsr[7]; + ctx->lfsr[7] = ctx->lfsr[8]; + ctx->lfsr[8] = ctx->lfsr[9]; + ctx->lfsr[9] = ctx->lfsr[10]; + ctx->lfsr[10] = ctx->lfsr[11]; + ctx->lfsr[11] = ctx->lfsr[12]; + ctx->lfsr[12] = ctx->lfsr[13]; + ctx->lfsr[13] = ctx->lfsr[14]; + ctx->lfsr[14] = ctx->lfsr[15]; + ctx->lfsr[15] = v; +} + +void +lfsr_keystream(SNOW_CTX *ctx) +{ + uint32_t s0 = ctx->lfsr[0]; + uint32_t s2 = ctx->lfsr[2]; + uint32_t s11 = ctx->lfsr[11]; + uint32_t v = ( + ((s0 << 8) & 0xffffff00) ^ + MULalpha[BYTE32(s0, 0)] ^ + s2 ^ + ((s11 >> 8) & 0x00ffffff) ^ + DIValpha[BYTE32(s11, 3)] + ); + + ctx->lfsr[0] = ctx->lfsr[1]; + ctx->lfsr[1] = ctx->lfsr[2]; + ctx->lfsr[2] = ctx->lfsr[3]; + ctx->lfsr[3] = ctx->lfsr[4]; + ctx->lfsr[4] = ctx->lfsr[5]; + ctx->lfsr[5] = ctx->lfsr[6]; + ctx->lfsr[6] = ctx->lfsr[7]; + ctx->lfsr[7] = ctx->lfsr[8]; + ctx->lfsr[8] = ctx->lfsr[9]; + ctx->lfsr[9] = ctx->lfsr[10]; + ctx->lfsr[10] = ctx->lfsr[11]; + ctx->lfsr[11] = ctx->lfsr[12]; + ctx->lfsr[12] = ctx->lfsr[13]; + ctx->lfsr[13] = ctx->lfsr[14]; + ctx->lfsr[14] = ctx->lfsr[15]; + ctx->lfsr[15] = v; +} + +uint32_t +clock_fsm(SNOW_CTX *ctx) +{ + uint32_t f = (ctx->lfsr[15] + ctx->fsm.r1) ^ ctx->fsm.r2; + uint32_t r = ctx->fsm.r2 + (ctx->fsm.r3 ^ ctx->lfsr[5]); + + ctx->fsm.r3 = snow_S2(ctx->fsm.r2); + ctx->fsm.r2 = snow_S1(ctx->fsm.r1); + ctx->fsm.r1 = r; + + return f; +} + +/* Public API */ +#define ONE 0xffffffff +/* reinterpret a char array as big-endian 32 bit unsigned integer array + * and select the element at index i. + */ +#define WORD_128(array, i) be32toh(((uint32_t *)array)[i]); + +struct snow_key_st +snow_array_to_key(const unsigned char *key, const unsigned char *iv) +{ + int i; + struct snow_key_st key_iv; + for (i = 0; i < 4; i++) { + key_iv.key[i] = WORD_128(key, i); + key_iv.iv[i] = WORD_128(iv, i); + } + + return key_iv; +} + +void +snow_init_lfsr_fsm(struct snow_key_st key, SNOW_CTX *ctx) +{ + assert(ctx!= NULL); + + memset(ctx, 0, sizeof(*ctx)); + ctx->lfsr[15] = key.key[3] ^ key.iv[0]; + ctx->lfsr[14] = key.key[2]; + ctx->lfsr[13] = key.key[1]; + ctx->lfsr[12] = key.key[0] ^ key.iv[1]; + ctx->lfsr[11] = key.key[3] ^ ONE; + ctx->lfsr[10] = key.key[2] ^ ONE ^ key.iv[2]; + ctx->lfsr[9] = key.key[1] ^ ONE ^ key.iv[3]; + ctx->lfsr[8] = key.key[0] ^ ONE; + ctx->lfsr[7] = key.key[3]; + ctx->lfsr[6] = key.key[2]; + ctx->lfsr[5] = key.key[1]; + ctx->lfsr[4] = key.key[0]; + ctx->lfsr[3] = key.key[3] ^ ONE; + ctx->lfsr[2] = key.key[2] ^ ONE; + ctx->lfsr[1] = key.key[1] ^ ONE; + ctx->lfsr[0] = key.key[0] ^ ONE; +} + +void +SNOW_set_key(struct snow_key_st key, SNOW_CTX *ctx) +{ + assert(ctx!= NULL); + int i = 0; + + snow_init_lfsr_fsm(key, ctx); + for (i = 0; i < 32; i++) { + lfsr_init(clock_fsm(ctx), ctx); + } +} + +void +SNOW_init(uint32_t countc, uint8_t bearer, uint8_t direction, + const char *confidentiality_key, SNOW_CTX *ctx) +{ + assert(ctx != NULL); + struct snow_key_st snow_key; + memset(&snow_key, 0, sizeof(snow_key)); + snow_key.key[3] = WORD_128(confidentiality_key, 0); + snow_key.key[2] = WORD_128(confidentiality_key, 1); + snow_key.key[1] = WORD_128(confidentiality_key, 2); + snow_key.key[0] = WORD_128(confidentiality_key, 3); + + snow_key.iv[3] = countc; + snow_key.iv[2] = ((bearer & 0x1F) << 27) | ((direction & 0x01) << 26); + snow_key.iv[1] = snow_key.iv[3]; + snow_key.iv[0] = snow_key.iv[2]; + + SNOW_set_key(snow_key, ctx); +} + +void +SNOW_gen_keystream(uint32_t *stream, size_t nb_word, SNOW_CTX *ctx) +{ + size_t i = 0; + assert(ctx != NULL); + assert(stream != NULL); + clock_fsm(ctx); + lfsr_keystream(ctx); + + for (i = 0; i < nb_word; i++) { + stream[i] = clock_fsm(ctx) ^ ctx->lfsr[0]; + lfsr_keystream(ctx); + } +} + +void +SNOW(size_t nb_byte, const unsigned char *in, unsigned char *out, SNOW_CTX *ctx) +{ + size_t i = 0; + size_t nb_word = nb_byte/4; + size_t r = nb_byte % 4; + uint32_t *in_word = (uint32_t*) in; + uint32_t *out_word = (uint32_t*) out; + assert(ctx != NULL); + assert(in != NULL); + assert(out != NULL); + + /* init */ + clock_fsm(ctx); + lfsr_keystream(ctx); + + for (i = 0; i < nb_word; i++) { + uint32_t f; + f = clock_fsm(ctx) ^ ctx->lfsr[0]; + out_word[i] = in_word[i] ^ be32toh(f); + lfsr_keystream(ctx); + } + + if (r) { + uint32_t f; + uint32_t last_out = 0; + uint32_t last_in = 0; + + f = clock_fsm(ctx) ^ ctx->lfsr[0]; + memcpy(&last_in, in + nb_word*4, r); + last_out = last_in ^ be32toh(f); + memcpy(out + nb_word*4, &last_out, r); + lfsr_keystream(ctx); + } +} diff --git a/lib/nas/common/security.c b/lib/nas/common/security.c index 8594aafc6..661259000 100644 --- a/lib/nas/common/security.c +++ b/lib/nas/common/security.c @@ -76,6 +76,7 @@ void ogs_nas_encrypt(uint8_t algorithm_identity, uint8_t direction, ogs_pkbuf_t *pkbuf) { uint8_t ivec[16]; + SNOW_CTX ctx; ogs_assert(knas_enc); ogs_assert(bearer <= 0x1f); @@ -86,8 +87,13 @@ void ogs_nas_encrypt(uint8_t algorithm_identity, switch (algorithm_identity) { case OGS_NAS_SECURITY_ALGORITHMS_128_EEA1: +#if 0 /* Issue #2581 : snow_3g_f8 have memory problem */ snow_3g_f8(knas_enc, count, bearer, direction, pkbuf->data, (pkbuf->len << 3)); +#else + SNOW_init(count, bearer, direction, (const char *)knas_enc, &ctx); + SNOW(pkbuf->len, pkbuf->data, pkbuf->data, &ctx); +#endif break; case OGS_NAS_SECURITY_ALGORITHMS_128_EEA2: count = htonl(count); diff --git a/tests/unit/security-test.c b/tests/unit/security-test.c index 25a38b63d..4bb5d3e8d 100644 --- a/tests/unit/security-test.c +++ b/tests/unit/security-test.c @@ -186,11 +186,20 @@ static void security_test5(abts_case *tc, void *data) uint8_t tmp[SECURITY_TEST5_LEN]; ogs_pkbuf_t *pkbuf = NULL; +#if 0 /* Issue #2581 : snow_3g_f8 have memory problem */ snow_3g_f8( ogs_hex_from_string(_ck, ck, sizeof(ck)), 0x72a4f20f, 0x0c, 1, ogs_hex_from_string(_plain, plain, sizeof(plain)), SECURITY_TEST5_BIT_LEN); +#else + SNOW_CTX ctx; + + ogs_hex_from_string(_plain, plain, sizeof(plain)); + SNOW_init(0x72a4f20f, 0x0c, 1, + ogs_hex_from_string(_ck, ck, sizeof(ck)), &ctx); + SNOW(SECURITY_TEST5_LEN, plain, plain, &ctx); +#endif ABTS_TRUE(tc, memcmp(plain, ogs_hex_from_string(_cipher, tmp, sizeof(tmp)), SECURITY_TEST5_LEN) == 0);