From 81343bc06fc08d8a3ba441e6038c9be1ed093fdc Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Wed, 12 Jul 2023 15:13:30 +1000 Subject: [PATCH] Add Curve25519 --- source/core/CMakeLists.txt | 2 + source/core/StarCurve25519.cpp | 50 + source/core/StarCurve25519.hpp | 25 + source/extern/CMakeLists.txt | 14 +- .../extern/curve25519/include/curve25519_dh.h | 53 + .../curve25519/include/ed25519_signature.h | 98 ++ .../curve25519/include/external_calls.h | 36 + source/extern/curve25519/source/BaseTypes.h | 121 ++ .../extern/curve25519/source/base_folding8.h | 1288 +++++++++++++++++ .../extern/curve25519/source/curve25519_dh.c | 208 +++ .../curve25519/source/curve25519_mehdi.c | 410 ++++++ .../curve25519/source/curve25519_mehdi.h | 175 +++ .../curve25519/source/curve25519_order.c | 155 ++ .../curve25519/source/curve25519_utils.c | 153 ++ .../extern/curve25519/source/custom_blind.c | 27 + .../extern/curve25519/source/custom_blind.h | 11 + .../extern/curve25519/source/ed25519_sign.c | 419 ++++++ .../extern/curve25519/source/ed25519_verify.c | 313 ++++ source/extern/curve25519/source/sha512.c | 294 ++++ source/extern/curve25519/source/sha512.h | 92 ++ 20 files changed, 3942 insertions(+), 2 deletions(-) create mode 100644 source/core/StarCurve25519.cpp create mode 100644 source/core/StarCurve25519.hpp create mode 100644 source/extern/curve25519/include/curve25519_dh.h create mode 100644 source/extern/curve25519/include/ed25519_signature.h create mode 100644 source/extern/curve25519/include/external_calls.h create mode 100644 source/extern/curve25519/source/BaseTypes.h create mode 100644 source/extern/curve25519/source/base_folding8.h create mode 100644 source/extern/curve25519/source/curve25519_dh.c create mode 100644 source/extern/curve25519/source/curve25519_mehdi.c create mode 100644 source/extern/curve25519/source/curve25519_mehdi.h create mode 100644 source/extern/curve25519/source/curve25519_order.c create mode 100644 source/extern/curve25519/source/curve25519_utils.c create mode 100644 source/extern/curve25519/source/custom_blind.c create mode 100644 source/extern/curve25519/source/custom_blind.h create mode 100644 source/extern/curve25519/source/ed25519_sign.c create mode 100644 source/extern/curve25519/source/ed25519_verify.c create mode 100644 source/extern/curve25519/source/sha512.c create mode 100644 source/extern/curve25519/source/sha512.h diff --git a/source/core/CMakeLists.txt b/source/core/CMakeLists.txt index 08701d7..1fd2aac 100644 --- a/source/core/CMakeLists.txt +++ b/source/core/CMakeLists.txt @@ -21,6 +21,7 @@ SET (star_core_HEADERS StarColor.hpp StarCompression.hpp StarConfig.hpp + StarCurve25519.hpp StarDataStream.hpp StarDataStreamDevices.hpp StarDataStreamExtra.hpp @@ -133,6 +134,7 @@ SET (star_core_SOURCES StarByteArray.cpp StarColor.cpp StarCompression.cpp + StarCurve25519.cpp StarDataStream.cpp StarDataStreamDevices.cpp StarDirectives.cpp diff --git a/source/core/StarCurve25519.cpp b/source/core/StarCurve25519.cpp new file mode 100644 index 0000000..f8f5451 --- /dev/null +++ b/source/core/StarCurve25519.cpp @@ -0,0 +1,50 @@ +#include "StarCurve25519.hpp" +#include "StarRandom.hpp" +#include "StarLogging.hpp" + +#include "curve25519/include/curve25519_dh.h" +#include "curve25519/include/ed25519_signature.h" + +namespace Star::Curve25519 { + +struct KeySet { + PrivateKey privateKey; + PublicKey publicKey; + + KeySet() { + SecretKey secret; + Random::randBytes(SecretKeySize).copyTo((char*)secret.data()); + + secret[0] &= 248; + secret[31] &= 127; + secret[31] |= 64; + + ed25519_CreateKeyPair(privateKey.data(), publicKey.data(), nullptr, secret.data()); + + Logger::info("Generated Curve25519 key-pair"); + } +}; + +static KeySet const& staticKeys() { + static KeySet keys; + + return keys; +} + +PrivateKey const& privateKey() { return staticKeys().privateKey; } + + + +Signature sign(void* data, size_t len) { + Signature signature; + ed25519_SignMessage(signature.data(), privateKey().data(), nullptr, (unsigned char*)data, len); + return signature; +} + +bool verify(uint8_t const* signature, uint8_t const* publicKey, void* data, size_t len) { + return ed25519_VerifySignature(signature, publicKey, (unsigned char*)data, len); +} + +PublicKey const& publicKey() { return staticKeys().publicKey; } + +} \ No newline at end of file diff --git a/source/core/StarCurve25519.hpp b/source/core/StarCurve25519.hpp new file mode 100644 index 0000000..15fe4d1 --- /dev/null +++ b/source/core/StarCurve25519.hpp @@ -0,0 +1,25 @@ +#ifndef STAR_CURVE_25519_HPP +#define STAR_CURVE_25519_HPP +#include "StarEncode.hpp" +#include "StarByteArray.hpp" +#include "StarArray.hpp" + +namespace Star::Curve25519 { + +constexpr size_t PublicKeySize = 32; +constexpr size_t SecretKeySize = 32; +constexpr size_t PrivateKeySize = 64; +constexpr size_t SignatureSize = 64; + +typedef Array PublicKey; +typedef Array SecretKey; +typedef Array PrivateKey; +typedef Array Signature; + +PublicKey const& publicKey(); +Signature sign(void* data, size_t len); +bool verify(uint8_t const* signature, uint8_t const* publicKey, void* data, size_t len); + +} + +#endif \ No newline at end of file diff --git a/source/extern/CMakeLists.txt b/source/extern/CMakeLists.txt index 0195b8f..e356c95 100644 --- a/source/extern/CMakeLists.txt +++ b/source/extern/CMakeLists.txt @@ -3,17 +3,19 @@ SET (OPUS_INSTALL_CMAKE_CONFIG_MODULE OFF) SET (OPUS_X86_MAY_HAVE_AVX OFF) SET (OPUS_X86_MAY_HAVE_SSE4_1 OFF) SET (OPUS_STACK_PROTECTOR OFF) - ADD_SUBDIRECTORY (opus) INCLUDE_DIRECTORIES ( ${STAR_EXTERN_INCLUDES} - opus + opus/include fmt lua ) SET (star_extern_HEADERS + curve25519/include/curve25519_dh.h + curve25519/include/ed25519_signature.h + curve25519/include/external_calls.h fmt/core.h fmt/format.h fmt/format-inl.h @@ -31,6 +33,14 @@ SET (star_extern_HEADERS ) SET (star_extern_SOURCES + curve25519/source/sha512.c + curve25519/source/curve25519_dh.c + curve25519/source/curve25519_mehdi.c + curve25519/source/curve25519_order.c + curve25519/source/curve25519_utils.c + curve25519/source/custom_blind.c + curve25519/source/ed25519_sign.c + curve25519/source/ed25519_verify.c xxhash.c fmt/format.cc lua/lapi.c diff --git a/source/extern/curve25519/include/curve25519_dh.h b/source/extern/curve25519/include/curve25519_dh.h new file mode 100644 index 0000000..258084b --- /dev/null +++ b/source/extern/curve25519/include/curve25519_dh.h @@ -0,0 +1,53 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2015 mehdi sotoodeh + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __curve25519_dh_key_exchange_h__ +#define __curve25519_dh_key_exchange_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Return public key associated with sk */ +/* sk will be trimmed on return */ +void curve25519_dh_CalculatePublicKey( + unsigned char *pk, /* [32-bytes] OUT: Public key */ + unsigned char *sk); /* [32-bytes] IN/OUT: Your secret key */ + +/* Faster alternative for curve25519_dh_CalculatePublicKey */ +/* sk will be trimmed on return */ +void curve25519_dh_CalculatePublicKey_fast( + unsigned char *pk, /* [32-bytes] OUT: Public key */ + unsigned char *sk); /* [32-bytes] IN/OUT: Your secret key */ + +/* sk will be trimmed on return */ +void curve25519_dh_CreateSharedKey( + unsigned char *shared, /* [32-bytes] OUT: Created shared key */ + const unsigned char *pk, /* [32-bytes] IN: Other side's public key */ + unsigned char *sk); /* [32-bytes] IN/OUT: Your secret key */ + +#ifdef __cplusplus +} +#endif +#endif /* __curve25519_dh_key_exchange_h__ */ \ No newline at end of file diff --git a/source/extern/curve25519/include/ed25519_signature.h b/source/extern/curve25519/include/ed25519_signature.h new file mode 100644 index 0000000..5831d9d --- /dev/null +++ b/source/extern/curve25519/include/ed25519_signature.h @@ -0,0 +1,98 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2015 mehdi sotoodeh + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __ed25519_signature_h__ +#define __ed25519_signature_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* -- ed25519-sign ------------------------------------------------------------- */ + +#define ed25519_public_key_size 32 +#define ed25519_secret_key_size 32 +#define ed25519_private_key_size 64 +#define ed25519_signature_size 64 + +/* Generate public key associated with the secret key */ +void ed25519_CreateKeyPair( + unsigned char *pubKey, /* OUT: public key */ + unsigned char *privKey, /* OUT: private key */ + const void *blinding, /* IN: [optional] null or blinding context */ + const unsigned char *sk); /* IN: secret key (32 bytes) */ + +/* Generate message signature */ +void ed25519_SignMessage( + unsigned char *signature, /* OUT:[64 bytes] signature (R,S) */ + const unsigned char *privKey, /* IN: [64 bytes] private key (sk,pk) */ + const void *blinding, /* IN: [optional] null or blinding context */ + const unsigned char *msg, /* IN: [msg_size bytes] message to sign */ + size_t msg_size); /* IN: size of message */ + +void *ed25519_Blinding_Init( + void *context, /* IO: null or ptr blinding context */ + const unsigned char *seed, /* IN: [size bytes] random blinding seed */ + size_t size); /* IN: size of blinding seed */ + +void ed25519_Blinding_Finish( + void *context); /* IN: blinding context */ + +/* -- ed25519-verify ----------------------------------------------------------- */ + +/* Single-phased signature validation. + Returns 1 for SUCCESS and 0 for FAILURE +*/ +int ed25519_VerifySignature( + const unsigned char *signature, /* IN: [64 bytes] signature (R,S) */ + const unsigned char *publicKey, /* IN: [32 bytes] public key */ + const unsigned char *msg, /* IN: [msg_size bytes] message to sign */ + size_t msg_size); /* IN: size of message */ + +/* First part of two-phase signature validation. + This function creates context specifc to a given public key. + Needs to be called once per public key +*/ +void * ed25519_Verify_Init( + void *context, /* IO: null or verify context to use */ + const unsigned char *publicKey); /* IN: [32 bytes] public key */ + +/* Second part of two-phase signature validation. + Input context is output of ed25519_Verify_Init() for associated public key. + Call it once for each message/signature pairs + Returns 1 for SUCCESS and 0 for FAILURE +*/ +int ed25519_Verify_Check( + const void *context, /* IN: created by ed25519_Verify_Init */ + const unsigned char *signature, /* IN: signature (R,S) */ + const unsigned char *msg, /* IN: message to sign */ + size_t msg_size); /* IN: size of message */ + +/* Free up context memory */ +void ed25519_Verify_Finish(void *ctx); + +#ifdef __cplusplus +} +#endif +#endif /* __ed25519_signature_h__ */ \ No newline at end of file diff --git a/source/extern/curve25519/include/external_calls.h b/source/extern/curve25519/include/external_calls.h new file mode 100644 index 0000000..7513b5f --- /dev/null +++ b/source/extern/curve25519/include/external_calls.h @@ -0,0 +1,36 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2015 mehdi sotoodeh + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __external_calls_h__ +#define __external_calls_h__ + +#include +#include + +#define mem_alloc(size) malloc(size) +#define mem_free(addr) free(addr) +#define mem_clear(addr,size) memset(addr,0,size) +#define mem_fill(addr,data,size) memset(addr,data,size) + +#endif /* __external_calls_h__ */ diff --git a/source/extern/curve25519/source/BaseTypes.h b/source/extern/curve25519/source/BaseTypes.h new file mode 100644 index 0000000..8d2e9a5 --- /dev/null +++ b/source/extern/curve25519/source/BaseTypes.h @@ -0,0 +1,121 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2015 mehdi sotoodeh + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __curve25519_base_type_h__ +#define __curve25519_base_type_h__ + +#include + +/* Little-endian as default */ +#ifndef ECP_CONFIG_BIG_ENDIAN +#define ECP_CONFIG_LITTLE_ENDIAN +#endif + +typedef unsigned char U8; +typedef signed char S8; + +#if defined(_MSC_VER) +typedef unsigned __int16 U16; +typedef signed __int16 S16; +typedef unsigned __int32 U32; +typedef signed __int32 S32; +typedef unsigned __int64 U64; +typedef signed __int64 S64; +#else +typedef uint16_t U16; +typedef int16_t S16; +typedef uint32_t U32; +typedef int32_t S32; +typedef uint64_t U64; +typedef int64_t S64; +#endif + +typedef unsigned int SZ; + +#ifdef ECP_CONFIG_BIG_ENDIAN +typedef union +{ + U16 u16; + S16 s16; + U8 bytes[2]; + struct { U8 b1, b0; } u8; + struct { S8 b1; U8 b0; } s8; +} M16; +typedef union +{ + U32 u32; + S32 s32; + U8 bytes[4]; + struct { U16 w1, w0; } u16; + struct { S16 w1; U16 w0; } s16; + struct { U8 b3, b2, b1, b0; } u8; + struct { M16 hi, lo; } m16; +} M32; +typedef union +{ + U64 u64; + S64 s64; + U8 bytes[8]; + struct { U32 hi, lo; } u32; + struct { S32 hi; U32 lo; } s32; + struct { U16 w3, w2, w1, w0; } u16; + struct { U8 b7, b6, b5, b4, b3, b2, b1, b0; } u8; + struct { M32 hi, lo; } m32; +} M64; +#else +typedef union +{ + U16 u16; + S16 s16; + U8 bytes[2]; + struct { U8 b0, b1; } u8; + struct { U8 b0; S8 b1; } s8; +} M16; +typedef union +{ + U32 u32; + S32 s32; + U8 bytes[4]; + struct { U16 w0, w1; } u16; + struct { U16 w0; S16 w1; } s16; + struct { U8 b0, b1, b2, b3; } u8; + struct { M16 lo, hi; } m16; +} M32; +typedef union +{ + U64 u64; + S64 s64; + U8 bytes[8]; + struct { U32 lo, hi; } u32; + struct { U32 lo; S32 hi; } s32; + struct { U16 w0, w1, w2, w3; } u16; + struct { U8 b0, b1, b2, b3, b4, b5, b6, b7; } u8; + struct { M32 lo, hi; } m32; +} M64; +#endif + +#define IN +#define OUT + +#endif diff --git a/source/extern/curve25519/source/base_folding8.h b/source/extern/curve25519/source/base_folding8.h new file mode 100644 index 0000000..a851175 --- /dev/null +++ b/source/extern/curve25519/source/base_folding8.h @@ -0,0 +1,1288 @@ +/* + This table is generated from all 256 permutations of SUM(P0,P1,..,P7) + where P_i = 2^(32i)*BasePoint +*/ + +const PA_POINT _w_base_folding8[256] = +{ + { /* P{0} */ + W256(0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000), + W256(0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000), + W256(0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000) + }, + { /* P{1} */ + W256(0xF58C3B85,0x2FBC93C6,0xFB8C0E19,0xCF932DC6,0x643D42C2,0x270B4898,0x33D4BA65,0x07CF9D3A), + W256(0xD740913E,0x9D103905,0xD140BEB3,0xFD399F05,0x688F8A09,0xA5C18434,0x98F81267,0x44FD2F92), + W256(0x877AAA68,0xABC91205,0xCCAAC49E,0x26D9E823,0xDD43598C,0x5A1B7DCB,0x9F0C65A8,0x6F117B68) + }, + { /* P{2} */ + W256(0x7B85C5E8,0x8765B69F,0xD168BAB2,0x6FF0678B,0x1D330F9B,0x3A70E77C,0xB0AF8E7C,0x3A5F6D51), + W256(0xA60DAC5F,0x61368756,0xEBABDC57,0x17E02F6A,0x4CCE0F7D,0x7F193F2D,0x89ECDCF0,0x20234A77), + W256(0x7178B252,0x76D20DB6,0xD51ED160,0x071C34F9,0xB3E41170,0xF62A4A20,0x3CFFE366,0x7CD68235) + }, + { /* P{3} */ + W256(0xA76C971F,0x812D6A74,0x0739F84D,0x1CECA25F,0x4102B810,0x27D06C3C,0x031906F7,0x7EDC1CC6), + W256(0x43BA112A,0x500519AD,0xAEBD3AD9,0xEBDA0D43,0x3E2CF3F0,0xF3F6B90C,0xA60CD4F5,0x0DE1829B), + W256(0x2AB6034B,0xF5472C0E,0xE480F342,0xBD4DBF55,0x0CCED266,0xD443D271,0x9C2DB4F7,0x4FE5CA42) + }, + { /* P{4} */ + W256(0x77D1F515,0xCD2A65E7,0x8FAA60F1,0x54899187,0xDABC06E5,0xB1B73BBC,0xA97CC9FB,0x654878CB), + W256(0x8DF6B0FE,0x51138EC7,0xE575F51B,0x5397DA89,0x717AF1B9,0x09207A1D,0x2B20D650,0x2102FDBA), + W256(0x055CE6A1,0x969EE405,0x1251AD29,0x36BCA768,0xAA7DA415,0x3A1AF517,0x29ECB2BA,0x0AD725DB) + }, + { /* P{5} */ + W256(0x601E59E8,0x0055C585,0x66480E60,0x8793342B,0xFE45E44C,0x3E14AAD0,0x4813CF2B,0x26EAD8E6), + W256(0x9C8462A4,0xCB75B8B6,0x67D31CD7,0x2DD86FC5,0x881342F6,0xCD1972EC,0x0FC12F2F,0x0975B597), + W256(0xDA5BA743,0x63CF2303,0x52F1BA6E,0x04BF9D81,0xAA7367DA,0x333790D0,0x9DF6C5EA,0x53467047) + }, + { /* P{6} */ + W256(0x7738657C,0x0AF0993C,0x47181BD2,0xA9FB4A47,0x3E9EC14A,0x55DDE7AB,0x37C8321C,0x0B9EC7F6), + W256(0x88035653,0x0AE97F7D,0x8D25068E,0x17FB7B10,0x3C1E8C9A,0x6328FC0E,0x50FE219B,0x5441585E), + W256(0x640F0146,0xCB52864C,0x317EF0D3,0x94562266,0x1595BB5D,0xB876F4C4,0xAF7F7713,0x4ED2F874) + }, + { /* P{7} */ + W256(0x74D2CDA7,0xFEB687D8,0xAE27FB22,0xB8042DC1,0x2C93ADCC,0x1564556D,0xE3A17816,0x11442D28), + W256(0x07F0C5D4,0xCEC33585,0x95B01C20,0xFB9E7EF9,0xDEA13143,0x0A869383,0xF5F8C59B,0x16C63A61), + W256(0xD6FED546,0xDED6638C,0x3803190E,0x1ABDB60B,0x6A614DA3,0xE0C56F15,0x9EDC6E88,0x04C54856) + }, + { /* P{8} */ + W256(0x12DDB0A4,0xD598639C,0xC024866B,0xA5D19F30,0x58FCE460,0xD17C2F03,0x2E095E8A,0x07A19515), + W256(0x9C2EC4DE,0x296FA9C5,0x4F84F3CB,0xBC8B61BF,0x17A8F908,0x1C7706D9,0x7AD3255D,0x63B795FC), + W256(0x389E5FC8,0xA8368F02,0xCF8DE43B,0x90433B02,0xC5412643,0xAFA1FD5D,0x032F0137,0x3E8FE83D) + }, + { /* P{9} */ + W256(0x17D3A339,0xB5F7F69A,0x36A01F1E,0x805E6145,0x9B01A221,0x08E62B6D,0x38F1898F,0x0AF83250), + W256(0xBDF01E71,0xBCC2BE89,0xC3280D0F,0x6758F9E1,0xCCF36C58,0xF2A56CDE,0x80FAACC0,0x1CDFBF7E), + W256(0x39BFB3B2,0x730688FB,0x07C06F81,0xF493C376,0x8DB1BA83,0xBDA608C2,0x63ECCA60,0x2990E0A2) + }, + { /* P{10} */ + W256(0x59DC4791,0xFCA8EA41,0x8B3AA058,0x0FAE3DAB,0x4EE996EB,0xBE13396F,0x51936C6F,0x379D09BB), + W256(0xF614AFFB,0xB6601A1B,0x210392EA,0x8360C886,0x56349198,0x4867333C,0xF049C42C,0x03224A6F), + W256(0x6FB88974,0x5E267A30,0x4F8FB990,0xBEB84F82,0x18C57B0D,0x6029B7B9,0xA2357DF1,0x60670BBE) + }, + { /* P{11} */ + W256(0xEC02DCD8,0xC8E97558,0x734215B0,0x70E6D52D,0xC97F37CC,0x5AD04683,0xC1D685AB,0x2C610AB3), + W256(0xE10C024F,0xABC333F4,0x672386CC,0x4F8149E4,0x4E7BF204,0x3BAD171C,0xE78F5067,0x4CEA190B), + W256(0x02F3325F,0x8D8D3A79,0xBF8ABDE9,0x549CBD48,0x11D19A0C,0x9DA1A0F6,0x372C817C,0x718BF518) + }, + { /* P{12} */ + W256(0x2381AD37,0x21C5E9F3,0xB96CD050,0xC340283E,0x3150ABCA,0xFBDEE471,0xC8FC9DB7,0x31B24DEE), + W256(0x2B76CCBB,0x2C160EED,0x54D82775,0x6DD5C36B,0xD5E0A5E9,0x7F278210,0xC59CF540,0x076FC47C), + W256(0x5F61DF81,0xBDF661D8,0x4EAEC5BD,0xFBB57FE5,0xE97CF86E,0x5AA7105E,0xD8D3CD95,0x00A448B6) + }, + { /* P{13} */ + W256(0x972952B6,0x584444A6,0xF3BA527C,0x1A2E4AF7,0xC1E4ED75,0x5AD4FFF4,0x3E78BA6F,0x4C05A24B), + W256(0xBF346A2E,0x124C55B2,0x3935E365,0xD103A43D,0xCB1495FA,0x057EC4BC,0x2715BAED,0x00ED1078), + W256(0xD51A6122,0xA0ACDB33,0x1637632C,0x371BC5B6,0xB00D94A1,0x8E34D701,0x7AF603FA,0x55A768B2) + }, + { /* P{14} */ + W256(0xB26499E1,0xA18985D8,0x3CEB5996,0xC1BC6208,0x5DF6F244,0x831CDAB3,0x630B203C,0x649754AF), + W256(0xB81E44C9,0xA3FBD80E,0xFCFBB70A,0xF7CB98EF,0xCFF94F56,0xF4AA5E2A,0x126D04AE,0x688D5981), + W256(0x8CBD0FFE,0xB3B29F90,0x269A99DB,0xFA623FB6,0xF70E7D34,0xB4B95B97,0x2A21E650,0x0D4247A0) + }, + { /* P{15} */ + W256(0x312ECED9,0x9EA81138,0xFD0E579D,0x85E9D4D4,0x23D68E7C,0x2308BA50,0xF6983F2F,0x36B2632B), + W256(0xF87A7D71,0x19A9F3F1,0x78B0D72D,0x60077D68,0x01A59BBF,0x8921D761,0xF8407391,0x262E84E2), + W256(0xD3285253,0xCDC70136,0x014124E2,0x7FFF27A4,0xDB2A2DF9,0xE29AC913,0x66338730,0x1D3BDC38) + }, + { /* P{16} */ + W256(0xACAD8EA2,0x583B04BF,0x148BE884,0x29B743E8,0x0810C5DB,0x2B1E583B,0x8EB3BBAA,0x2B5449E5), + W256(0xEB3DBE47,0x5F3A7562,0x8EBDA0B8,0xF7EA3854,0x45747299,0x00C3E531,0x1627D551,0x1304E9E7), + W256(0x6ADC9CFE,0x789814D2,0x8B48DD0B,0x3C1BAB3F,0xF979C60A,0xDA0FE1FF,0x7C2DD693,0x4468DE2D) + }, + { /* P{17} */ + W256(0xE3BC6748,0x2118278D,0xD0B20EF7,0xE71FFD60,0xC67BB198,0xF551BE51,0xD0543D4D,0x26A13664), + W256(0x13A339EE,0x29522D3B,0x6CD89529,0x85522550,0xACF4F0F1,0xDFEA3AD4,0x7942742E,0x49D76BBA), + W256(0x8D56E61D,0x14FA4233,0xC351299A,0x191D3946,0xA7ADB185,0x247D576D,0xA8FCEDC2,0x4E1FAFE3) + }, + { /* P{18} */ + W256(0x6B45EA9A,0x4B413B87,0xFA00AC34,0xF6C48949,0x81AC11D2,0x1A1F2362,0xDD980A49,0x30F3DDE7), + W256(0xBCCBC178,0x2D8BA97F,0x519FE02D,0xAEB46997,0xB79E5C67,0xB84B8FD5,0x143A7698,0x5B91B0FB), + W256(0x3C1C04D5,0xCA900BC5,0xA39B659C,0xF169E39F,0x08A5AFF2,0x8D2ACF06,0x7C985580,0x26416E52) + }, + { /* P{19} */ + W256(0xC3366BDF,0x9E6C7295,0xB28D0A8F,0x4808B22D,0xA7082921,0xF7375D06,0x7280CB9D,0x072AE441), + W256(0x7E73663A,0xAD4E9526,0x6402BF65,0xC26E23FF,0x374ECB55,0x34E1DAB6,0xAC128163,0x4F1EADF2), + W256(0xC7581FDD,0xDF30E1BB,0x61A63C23,0xB3E73F2E,0xA16D9C3D,0xA750CFD5,0x497B7242,0x719F9FCF) + }, + { /* P{20} */ + W256(0x236A044C,0x15E7053D,0x3B8D87E3,0x3CDDBCB1,0xD321A828,0x519960D2,0x0FC5BBA4,0x4E559A0F), + W256(0x9C12701C,0xFE00E876,0x039C3B5F,0x95DCDC0A,0x0C02EB1B,0xC169454B,0x5F87530C,0x727021D3), + W256(0x27DF241E,0xA5710407,0xB2900D36,0xDF45EFAA,0x60A69ADE,0xFE6EDB5C,0x07BBC01D,0x64FCB730) + }, + { /* P{21} */ + W256(0x6FD390CA,0x38EF58CC,0x171A98FC,0xEF786575,0xC442D65F,0x8850B78F,0x6FD086EF,0x6F34C66D), + W256(0x3898DC04,0x93F3CBB4,0x4307B727,0x0791FFB2,0xCE34981D,0xD7BD8096,0x8B849F6D,0x0B598B8E), + W256(0x0CC2F689,0x11CFC18A,0xB529CE2A,0x81114607,0xC00B5940,0x0A9BC046,0xB1AC66C8,0x412128B0) + }, + { /* P{22} */ + W256(0xA3D84743,0x8B5F16B3,0x20EB9FF7,0x809C9763,0xDF9462C3,0xABC50529,0xC4CC6F52,0x1C648CE1), + W256(0xE2EB0307,0xF2674254,0x2DA3AA98,0xA835DF64,0x07DD382C,0x377941CE,0xF60597C6,0x09603B84), + W256(0xC9E55150,0x1840B2D2,0x390C7082,0x0CEFA12F,0xB6D2A82F,0xCB58A4A0,0xE4BF3457,0x4EC62E6E) + }, + { /* P{23} */ + W256(0xF571047D,0xCF391089,0x001D01B2,0xADA730B7,0xB8DABA3D,0x18871AA4,0xF61CCCE8,0x34D6411B), + W256(0x9F79EF24,0x0C14A627,0x68276CE3,0x1E44AF93,0xAF5E5CEB,0xB72EF4FF,0x4AC56322,0x72237BAD), + W256(0x37C0DC1F,0x9E293ED7,0xBEFB66DB,0xE165F9D6,0x325DD9F3,0xAC1B10FC,0x8009D865,0x3E5ECBE4) + }, + { /* P{24} */ + W256(0xE8B81044,0x59733185,0x108BAC60,0xE2E029E4,0x6908254B,0x9D9DEDF4,0xBFC317ED,0x4F8D3ADF), + W256(0x25AF0DCC,0x078B7334,0x5067BA11,0x0472D1D3,0x38191434,0x37848B52,0xBD371A71,0x543107B9), + W256(0xC08D3984,0x6B64607C,0xC89F5B2C,0xD44F8EB9,0x77523565,0x805CD88B,0xAE0B9CCB,0x0CE8C056) + }, + { /* P{25} */ + W256(0xB3819AB4,0xB8B66511,0xC418154B,0x5309B011,0x60E07CAF,0x514F7CB5,0x66A3F80B,0x47FD0855), + W256(0x76E05CAA,0xBA4EADCC,0x3A54A171,0x9D40E878,0x26DA9727,0x7C9542ED,0x2F23CDCA,0x46440C7A), + W256(0x431334CF,0x80102AB0,0x58C0CE70,0xCD1B2787,0x0154B9BB,0xDA3CCBEC,0x740E3E26,0x233A3339) + }, + { /* P{26} */ + W256(0x03FF1BB4,0x66B1DB86,0x4F427346,0xECCBFD7B,0x730E1064,0xF5C0EF08,0x98AC2743,0x6AD4EF70), + W256(0xA78B10E4,0x6B409241,0x7A431C57,0xD3313951,0x6D66DF43,0xF2423B52,0x5B0B4EC0,0x223EE393), + W256(0x9067E8CC,0xA882277C,0x10A85F5E,0x4C113D37,0x569CE51F,0x77A224C5,0x23FF2F06,0x77B028B6) + }, + { /* P{27} */ + W256(0x0D549385,0x5B209F06,0x63C235E0,0xA08976F7,0x5A3054FA,0x3D4C47B6,0xCEEC9D5F,0x60658F6D), + W256(0x06156933,0x3CC5FE1E,0x7C4D221A,0x56CB4582,0x6BDF48A7,0x913CDCDD,0x913F6B94,0x1FF62032), + W256(0x7095B31B,0xE5E35AFA,0xB528BD84,0xADEBE9A8,0x111204F7,0x774AC00F,0xAF32BA8A,0x73473323) + }, + { /* P{28} */ + W256(0xF4F67B48,0x6CC34769,0x25194E16,0xECA62A7C,0x9E71DE23,0x1D302A91,0xA0CA9C66,0x3B64FCF1), + W256(0x58B1B8C0,0x6C0F0B9C,0x293BB326,0x3795DB5D,0x6B411555,0x5C8E6A48,0x65336921,0x29275DB6), + W256(0x0E8B907B,0x30C8F772,0xD18547B0,0x7DACFAAB,0xFFED56E8,0xA786345F,0x089751C9,0x7418665A) + }, + { /* P{29} */ + W256(0xA1DAE8E1,0xCCE6BDF4,0x9BAFBB60,0xD56EB17C,0x1C286590,0x3DD92F76,0x43F38AED,0x5E5C02DA), + W256(0x366C497D,0x0B884A8E,0x50F8071B,0x2D68611C,0x4F7D7AD7,0x6FEDE5E9,0xC9190A34,0x1508210F), + W256(0xA50625CC,0x380903E6,0x2DE33381,0xF4E3C123,0x6DBD4874,0x3CE70681,0xB66B3A9C,0x3437DE93) + }, + { /* P{30} */ + W256(0x410A634F,0xDCB489C7,0xC5F43C21,0xB966CA7B,0x627E497D,0xC8151DD3,0x444C095B,0x7EA1541E), + W256(0x0EE54670,0xB443ACB8,0xB8F40C8B,0x34AD3FF2,0x689D8B4C,0xBA037921,0x1A082A71,0x405952A4), + W256(0x5142ABC6,0x56B8D889,0x540DE993,0x86ED618F,0xCC7FBF1E,0x72A0CD17,0x468B4E24,0x044745CA) + }, + { /* P{31} */ + W256(0xF5BB9F3B,0x58FA4EBE,0xB99C8573,0x1977B7DD,0x81D0E028,0x07EBEDBB,0xC9609C12,0x6491BA77), + W256(0xFF8604B6,0x2FBD585A,0xC0B44E60,0x9FE55125,0xA3AEAC8A,0x9BA69F90,0x15BE487D,0x05393A06), + W256(0xBB6B377E,0x67CD556F,0x17735944,0xA89D57FF,0x0C137883,0x38DB2167,0x90BC96CB,0x3B77872F) + }, + { /* P{32} */ + W256(0x305B2F51,0x96EEBFFB,0x889596B8,0xD3F938AD,0x46D5DD25,0xF0F52DC7,0xBB3A0095,0x57968290), + W256(0x8C58AEDC,0x4637974E,0xABF041A4,0xB9EF22FB,0xE980718A,0xE185D956,0xB143A8A6,0x2F1B78FA), + W256(0x0A20E101,0xF71AB843,0x24F0EC47,0xF393658D,0x6EE2EED1,0xCF7509A8,0xDC2AA3E1,0x7DC43E35) + }, + { /* P{33} */ + W256(0x8E260E07,0x39B3240A,0x62871AC8,0x852074F4,0xA44E0939,0xE2B30D7B,0xA0ABAAE8,0x46024D80), + W256(0xD3C313BF,0xB2B999B9,0x6E51EBB2,0x2D5ABD52,0xEE0E550F,0x90BBDBBB,0x98CCCE19,0x68DA131C), + W256(0x54A41B0A,0xEC23DE8E,0xB782780D,0xCF7B9637,0x939E311E,0x3CFD7049,0x0EA55972,0x597A7817) + }, + { /* P{34} */ + W256(0x06BAAFDA,0xBC045FDE,0xFB5A4416,0x47739AE0,0x5D2EE4A6,0x7C8463D8,0x04374AD2,0x2203EAC5), + W256(0xA05C01E7,0x0EFF92FE,0x895FB7CC,0x75F7039C,0x9404E0F8,0x8D6A8217,0x8A9A737A,0x573560A5), + W256(0x59DD3897,0x86782D19,0x70D83750,0x60123667,0xFCE034C3,0x9B25D884,0x01E23583,0x3E1460C5) + }, + { /* P{35} */ + W256(0x016C8B1C,0x0532F811,0xD136BA45,0x2E95ED3F,0xE61135AB,0x63A63935,0x998DDB46,0x4528B81A), + W256(0xB2E76CB2,0xBB03507C,0x6FA0507E,0x4974972D,0x909195F3,0xAC4EF385,0x584F70A3,0x06057D24), + W256(0x8C90F978,0x54A5662F,0x2F7B10C4,0xCBC6CCF5,0x865DB58B,0x448B019B,0x95F99DED,0x42420EE3) + }, + { /* P{36} */ + W256(0xB5714CEB,0x30BAF789,0x974FD937,0xB8AA475F,0x0F057B03,0x433FA765,0x4E4B8810,0x1F64562F), + W256(0x95C2FD9C,0x563EE272,0xA9B8DC68,0x5DD036C4,0x036007BA,0x7C530EF9,0xDBD2061B,0x39F11784), + W256(0x37138FAB,0xAB6C4500,0x34F6DADC,0xC27F3315,0x8F069781,0x0210194C,0x9E2F307A,0x50E31631) + }, + { /* P{37} */ + W256(0xC3B0007B,0x472EA0BC,0x45EB13C5,0xE17CA69E,0x819BFA26,0x6278A077,0xB21B3D0A,0x09FFC1DA), + W256(0x8DB01743,0x335F8D6C,0x476C43B0,0x2B131C1C,0x92DDC403,0x6FC74962,0x1B87720C,0x4FB1E3E1), + W256(0x93B99DD4,0xE7355CBC,0x68EDCAF2,0xD1C37535,0x113C1F1A,0xF8C2A48A,0x7D5EB4B0,0x78A7A057) + }, + { /* P{38} */ + W256(0x60456CBB,0xBE511469,0x8D5D8C2E,0x1F30B9FD,0xB4C04589,0xB87B3385,0x4351534C,0x554247D4), + W256(0x55283C9E,0x101625E2,0xC1E61FB8,0xFAD2395D,0x6B7D5564,0xC3534059,0x96E1D1F2,0x521864BF), + W256(0xB9332CC5,0xF4FFC63A,0xA52BD4A8,0x918219B2,0x841911C2,0xB9DA028E,0xC36C5963,0x6B1FC8BC) + }, + { /* P{39} */ + W256(0xFF5EFDCF,0xC69C8CBA,0x8EF90996,0x2911C701,0x86929CD5,0xC9245FA6,0x403C2507,0x680DFC97), + W256(0xC62E53B7,0x86C5EE26,0x217CC5D7,0x5F38E8D3,0x3BE42BCE,0xBE8F603D,0x0C2B9113,0x1FA5774D), + W256(0x2670BEED,0x89ECBFFB,0x6138312F,0x02950E5D,0x20860EA8,0xD4961611,0xE64C338F,0x1F301F21) + }, + { /* P{40} */ + W256(0x75E3FB78,0x39D004C9,0x29B114E0,0x18B6E865,0xD16C3194,0x38EBE25F,0x9E79F5CF,0x607D2344), + W256(0x2338841D,0xCE240F2C,0x8631E5D1,0xF0ECCD75,0xF18A552D,0xA57EE5F1,0x1C9B3233,0x7AB87BC8), + W256(0x1B17760E,0x7E7F7150,0xE158A26E,0xB6632A86,0xBE0AC1D5,0x39EA5398,0x503BA911,0x68A56D9D) + }, + { /* P{41} */ + W256(0xE76FDB4D,0x23CB640C,0x3F0908FE,0x47E31113,0xD0B34BD7,0xCDCBAC03,0x837C25B8,0x7F82DC07), + W256(0x71A8C4DB,0xD8E96E52,0x7CFDB8C9,0x23294A50,0x8AF236C6,0x46960665,0xBA025941,0x399A2E1D), + W256(0x3A40D717,0xF4286F37,0xA6C7AB20,0x1B14D057,0x52F67CCA,0x83A1C822,0x1B1CA416,0x7CC9285E) + }, + { /* P{42} */ + W256(0xC8A5BC9B,0xFFE05716,0x465E9F43,0x066A99E4,0x4A91D729,0x5F1F7C8B,0x1C435B3B,0x24102BD9), + W256(0xF4CA0F68,0xF20B8F9E,0xE0AEF35B,0xDC05F306,0x2D531E9A,0xB4666F04,0x1B535EE9,0x383FF5D3), + W256(0x442B19AA,0x84DCD7CB,0xE6B5984D,0x4118DB5F,0x21A7DEC1,0x4FE5DD46,0xD86EF74F,0x1CC49092) + }, + { /* P{43} */ + W256(0xB44C3A2F,0x8B29913A,0xAA52080F,0xCD694C5D,0x5ADD88D4,0x18F93889,0x901BC6A7,0x63EAAAC5), + W256(0xB5715B8C,0x1D1D5492,0xD839A828,0xA4200D1D,0x2B183D76,0xBCAC4824,0x4C296927,0x0CBB60C5), + W256(0x4BBEB387,0x80FBCDFE,0xEC5778E7,0x2A83408C,0x34339AF7,0x1F78D31B,0xC8A8EF0D,0x3F9D64C8) + }, + { /* P{44} */ + W256(0x811A5A5A,0x9DCEEBBE,0x92764FEE,0xA3266706,0x3CAF98AA,0x90359A3C,0xFF96A438,0x2B83D213), + W256(0xD47173AB,0xFACDC91F,0x5D2F974B,0xADEA7B2C,0x6FDF8E35,0xC13603D0,0xC639EF42,0x30435392), + W256(0x8CC47E2C,0x1263D1AC,0x0BA468D7,0xE21C9E3E,0xF0204559,0x537A318F,0x2FB95AC5,0x10AA737E) + }, + { /* P{45} */ + W256(0x2006DE8F,0x85B007AA,0xF6BB993C,0xBDE46C9D,0xFEB58E38,0x7BC28481,0x6212A44A,0x78B9FDC3), + W256(0xDECB7244,0xA5EA6C05,0x4E0D68B8,0xD24015A7,0x9C10E916,0x546C84B6,0x7BAC682C,0x2B5447C6), + W256(0x71687F56,0x7365F032,0xD4E60EA8,0x8289C896,0xE6A09396,0x419A7CB6,0xD6400EF0,0x3DD7F389) + }, + { /* P{46} */ + W256(0xA70E980D,0xCC2FD8E0,0x8381B94F,0x6DDF7029,0x480C7F27,0xF50664B1,0x231AC201,0x49058F81), + W256(0x2B002594,0x068ACF53,0x51BDE407,0x2DB03C16,0xA06CB4BD,0xAE564BDB,0x345E692A,0x4CEF9672), + W256(0x64EF121E,0x83F6ACCF,0x03C67508,0xB662C5CD,0x5E8EC922,0x0096E089,0x6365F801,0x651F8062) + }, + { /* P{47} */ + W256(0x446A6929,0x16527736,0x6A71196E,0x065115B5,0xF29C4EAB,0xDB7CE2F7,0x77CCE053,0x21E2AE16), + W256(0x163B9183,0x07F1B268,0x8E5270C2,0x53A98108,0xFBAA6979,0x6C820AF9,0xFA55E6E9,0x5962BC13), + W256(0xE021520D,0x287E4E5C,0x94C883CD,0x6863C664,0x5790868F,0x58163F9D,0x7E31C55A,0x753907EC) + }, + { /* P{48} */ + W256(0x7B784751,0x9AA6B27C,0x478EBAA4,0x324BEC2C,0x6AEC068F,0xE9ED08E6,0x1289EA7F,0x2201F338), + W256(0x1D82D9E5,0x88B6F93F,0x38AF97B8,0xC753DB55,0x2390C879,0x1BF3B161,0x3633ED25,0x138E33B3), + W256(0x7B9CD213,0xB6B55F37,0x20636109,0x2898D18F,0xC10D1935,0x0B5507EE,0xE7915B1C,0x09F8A06A) + }, + { /* P{49} */ + W256(0xA156BEE1,0x2D49686E,0x1C1DA03B,0x2324E89C,0xAC203D50,0xD04411D1,0x1BA09051,0x4C676623), + W256(0xAAD02187,0xD3AFC637,0x4A427480,0xDBD9DF22,0x0A76A644,0xA1667506,0x219197E9,0x4D4F7873), + W256(0x7C9FE358,0x62CCF2C6,0x62498039,0x9247D76E,0xD7566ABE,0xF38B6CD8,0xC416D3CE,0x75B11CF8) + }, + { /* P{50} */ + W256(0xD35FFB34,0x263738AE,0x08F9D4CE,0x832A1BE5,0xB79AB05B,0x85A8A919,0xA2783D74,0x249A81E3), + W256(0x1829704F,0x715BB053,0x543DA8B4,0x1EC6AC53,0x12478E5E,0xFDA431A3,0x496D50A6,0x499021E4), + W256(0x548CDCB6,0x899A7EE9,0x22E94B30,0x6C1DD7B6,0xCC3BC5CA,0xC83AC3B4,0xDD006024,0x7058121D) + }, + { /* P{51} */ + W256(0xD0A8E8DA,0x655ADE93,0xF3B0B528,0x54028BC0,0x7068729D,0xFEEB9E37,0x63D404AB,0x2F6D0357), + W256(0x57911CD7,0x319E7E40,0x4A053A89,0x48CD0556,0x1711B185,0x8DB0F64A,0x3CC73FD4,0x23F42F87), + W256(0xFD5FEE8E,0x0E966846,0x34D2C0AE,0x5E0BB862,0x80FD5963,0x60D4F63B,0xD8E4DBBC,0x68DD930A) + }, + { /* P{52} */ + W256(0x49349375,0x9FC17ECB,0x4158C55C,0x5E732FFB,0xFBDC6DED,0x8759BFAB,0x7B86639D,0x0A052F82), + W256(0x777962B3,0xE04CC8D1,0x63464020,0x8835C295,0x10F7A751,0x7D2E941F,0x6EE28E97,0x50400CC1), + W256(0xE09B6BB2,0x654A5E35,0x7997775E,0x63A31E9C,0x3416C504,0x78190EB8,0x2BB6F3A0,0x304DBDF5) + }, + { /* P{53} */ + W256(0x9FCA639C,0xC0F200E9,0x35F7F0E3,0x54D06B32,0x363B7D83,0xED9121BC,0x4ACDABF0,0x3E5EA2D9), + W256(0x95849740,0x3F317C55,0xBD56A2F2,0x639A7ED4,0x529C3A7A,0x1CCAA5F1,0x0989B5B0,0x5652C4F5), + W256(0xB99E3A9F,0x1BB512BB,0xBEC8021C,0x4EFC5E35,0x687C6E35,0x1BEEDE8C,0xFC28959C,0x6D7F7CD4) + }, + { /* P{54} */ + W256(0xD6AE865A,0x37F602FE,0x5644C995,0x308FBCA2,0x77EAEAE2,0x0ECC084C,0xB4CDC74F,0x7DB8FE19), + W256(0x1377ADD9,0x2641E359,0xB1A41953,0x3F7E961C,0x401F2F9F,0x968AFEE2,0x5A37BBEF,0x2E92A64E), + W256(0x93ACC7FC,0xF20F4797,0x40BAB1E7,0xC5485755,0x7F03710D,0x7C83E40E,0x6F44A6EE,0x69F8FD42) + }, + { /* P{55} */ + W256(0x56A50DDA,0xF381AD3B,0xF2E4A6FA,0xD6DE8923,0x64D7DCDC,0xB3759362,0x7C2E641E,0x3EAD5CD6), + W256(0x845B8D5C,0x910AFC9F,0xA1A43909,0x714AC6E6,0x06B29A0B,0x80F27D93,0x1E41F09A,0x6532988A), + W256(0xC88AE13C,0x552C67DF,0xBF55730F,0x8F591C65,0x2FE7A905,0x5B519E2C,0x77E7A32F,0x6E7F879A) + }, + { /* P{56} */ + W256(0x6D2128F5,0x70E89575,0x113E2943,0x11B2E65D,0x502A27E3,0xCC14522F,0x5223D989,0x0E6258C5), + W256(0x82EC85AE,0x5F939035,0x8535FD78,0xAD15CF95,0xF786332F,0x756CDB90,0x5DA65E0C,0x2D18D5ED), + W256(0x9BDFC49A,0x8AD6B63E,0xE7F7C76D,0xA1B3286A,0x56D495F6,0xB0E423D8,0xACD6FBC6,0x1461D531) + }, + { /* P{57} */ + W256(0x136B2904,0x277B0FF7,0xA8D39066,0x6F94FDAE,0x56101BD9,0xE9A20FDC,0xB892705E,0x4226AB45), + W256(0x5F57047B,0x9770DCB1,0xC5CF4123,0xAA2F99A9,0xBBB7F32C,0xCA99DA38,0x6A654557,0x5B74A519), + W256(0x494DB970,0x2C3AA0D1,0xAF7CA799,0xF8FDB612,0xC7B28AE3,0xD6E75DEE,0x982B6B0B,0x0CA5047C) + }, + { /* P{58} */ + W256(0x5D5AB1F3,0xA096097E,0x30D14C4D,0x55E6AC6B,0x40B47347,0x0E787B5B,0x7172E37E,0x27FDEB5F), + W256(0x03373C3F,0x5F328AD3,0x3B3038A6,0x2E79AD7E,0xDE222F9D,0x39DC8F94,0x1B18555A,0x34F4B6D1), + W256(0xFCA72FBA,0xFBD02A20,0x4FCADB53,0x2827ACB2,0xEE77588C,0xEBC9A4E0,0xED302543,0x7AFCF628) + }, + { /* P{59} */ + W256(0x5E1A397A,0xB85A436C,0xABFD5DC6,0xE51B3D09,0x351E57A6,0x09509CB9,0xB3C8F3DB,0x25A1C873), + W256(0x23FD941E,0x86F2BEBE,0xFC6E6286,0xF568F06C,0x2E4D97A3,0x736AB7BC,0x999BB98D,0x682C7169), + W256(0x0D5C4162,0x0B156F55,0x2754D6C2,0x2482776F,0xBDC504AD,0xC2D1F94D,0xD5C203CA,0x1D018E5E) + }, + { /* P{60} */ + W256(0x29ED5B5A,0x43BF7735,0x9BE0D0DA,0x5EDD0E51,0x6DA65344,0x6D426429,0xC489C0ED,0x34A7969B), + W256(0xCD5D792C,0x1643AB04,0x7627E597,0xD91D4D11,0xC4545CEA,0x42679317,0x268698CC,0x4D661E38), + W256(0xD7CA94C6,0xE6FFBA43,0x5BFFBCE7,0xFD395C38,0x26310616,0x27907028,0x96F73C17,0x5E78150A) + }, + { /* P{61} */ + W256(0xFA433F7C,0x763966FC,0x6903B07E,0xB90424C0,0xCE43E341,0x2A9F9B88,0xA8EDA21A,0x55D4C871), + W256(0x88047FFE,0x4860D96D,0x97CCFDAB,0xD5A0D550,0x768E3FDA,0x05DB5A13,0x5FF6230E,0x3F33F026), + W256(0x183AA8B6,0x48698D99,0xE3871279,0x8BEBA46A,0x7767EE98,0x40F762BC,0x6913B8DB,0x26BD664E) + }, + { /* P{62} */ + W256(0xCBF721F9,0x6E61C09C,0xD47EF6E1,0xAF380D23,0x338EAB76,0x82784AE2,0x167F4FDE,0x31816AC9), + W256(0xC6BDB362,0xDEE539F6,0x9960C22F,0x591D4144,0xA3A085C7,0xA5B1E10D,0x2FDFA6FE,0x2EF298A4), + W256(0xA6B817C5,0xEA4492C9,0x961B2033,0x72CD8C86,0x88F3A779,0x83FABA60,0xBBB5E2C7,0x66012E6A) + }, + { /* P{63} */ + W256(0x2F14C065,0x3289BB63,0x95E2F595,0xD4A81CFE,0xABF8B5B3,0xB616CBDE,0x7A49FEFF,0x5C907F1F), + W256(0x1A7C3ADE,0x17B5D117,0x8F5FE973,0xEDE22672,0x54A3C3E3,0x184C3ADF,0x642DFDCA,0x40DDEDBB), + W256(0x79BC659F,0x5F43C051,0x2EBE945F,0x5324FAE0,0x6798EB6A,0xC35FBCBE,0x2F0245E7,0x065E8BC2) + }, + { /* P{64} */ + W256(0xC80C1AC0,0xA66DCC9D,0x1B38A436,0x97A05CF4,0x95DBD7C6,0xA7EBF3BE,0x8D7E7DAB,0x7DA0B8F6), + W256(0x385675A6,0xEF782014,0xAAFDA9E8,0xA2649F30,0x5CDFA8CB,0x4CD1EB50,0x1D4DC0B3,0x46115ABA), + W256(0xC3B5DA76,0xD40F1953,0x21119E9B,0x1DAC6F73,0xFEB25960,0x03CC6021,0x83674B4B,0x5A5F887E) + }, + { /* P{65} */ + W256(0x0CA2C1F4,0x0A8D6018,0xCC68DF40,0x815EB0DB,0xB82F4E99,0xD7E67A47,0x607F15C0,0x45A02890), + W256(0xFD41F184,0xFEF366D1,0x01CFE11E,0x8B694A11,0x0150A74D,0x4B39E15E,0x6AD351BA,0x4013F03D), + W256(0x6EE065CC,0xBD0282DC,0x224AE646,0x36B994FD,0xFEBCE874,0x534E9AD8,0xD9F06E4F,0x482255C1) + }, + { /* P{66} */ + W256(0x05928A7A,0x1E6B0A56,0x25DB60C2,0x1D5B9151,0xCFC4755B,0xFA8792C0,0x55427D2E,0x2086F7FE), + W256(0x8D2CA3EA,0x0204AC4E,0xEA1927C7,0x299BD9AA,0xF325CDC0,0x0E6883EA,0x65B65B44,0x62E98840), + W256(0x77FAABDB,0x7775A789,0x6BBB5798,0x054B6258,0x9568BA16,0x210A7EBC,0xE60AB511,0x1DAD6E30) + }, + { /* P{67} */ + W256(0x628ED648,0xEF459F08,0x90E1486A,0x57A3C57B,0xEB699406,0x54EB20D2,0x7C2A796F,0x298E3AE2), + W256(0x080F1721,0xE221B34A,0xC1128E4F,0x394438A7,0x7D18ECFE,0xC370CE8B,0xBF53150B,0x55C5E6A7), + W256(0xB03C4AB0,0xFEFB6E91,0x20FEE7C4,0x54B38D6F,0x3C3D04AC,0x395A19AF,0x7A8B9170,0x79DDF3A9) + }, + { /* P{68} */ + W256(0x71CEF800,0x3C03EACF,0xCA8AFEBB,0x90367544,0x6A29C477,0x383FEA28,0xBC655462,0x4E8593B0), + W256(0xA3E5638C,0x12DE114A,0x29C4F20D,0xBA2A4AA9,0x7B8B13A3,0x56B0D29D,0x7B9B7944,0x6BB91A49), + W256(0xC5E7D206,0x2A49E646,0x9263C445,0xB13EF9CD,0xEDAB529E,0x50AB6CE8,0xB0EBE39B,0x20CF7D79) + }, + { /* P{69} */ + W256(0x8AE75C48,0xCBD28F4E,0x44000B60,0x3CDE0291,0x98BC2170,0x373BB9C8,0x9F570886,0x7C118853), + W256(0xF0FE7DCA,0x7DB4939D,0xCBA951CE,0xF50EB90F,0x357E1D1D,0x098BE61C,0x8899469D,0x02356237), + W256(0xE15A4C03,0x20F6EFFA,0x3C778E05,0x2F470A94,0xFC99DE67,0x79F50A03,0xD1061483,0x38D20188) + }, + { /* P{70} */ + W256(0x118CA612,0x05B6B816,0x2ACB38EE,0x76293423,0xD4C85D20,0x3ADDAB78,0xF26BE705,0x2872E796), + W256(0x0CE21195,0x0F2D95B4,0xE160884E,0x14029E27,0x6A05BAE9,0x3DCD49F7,0x7BEB7CA6,0x23B7DE35), + W256(0xC0C99A90,0x78D00CBA,0x964DD704,0xC48A93F4,0x61B7DA2A,0xA010301C,0x3F0DA51E,0x4E307A03) + }, + { /* P{71} */ + W256(0x7D90930B,0xE3906810,0x0926081A,0xC4D5C019,0x7EEE2811,0xEAC88198,0x7166A974,0x369E7A03), + W256(0xF32A7AA7,0x4EB04D2E,0x23486432,0xC333E926,0x5BB4BBD2,0x67F2859D,0x362DB995,0x340611CE), + W256(0x69C77C9C,0xDDE8F5CA,0x5612A945,0x9B8AE19D,0x3B0B7046,0xF989FEFB,0x2FA594D5,0x3DD66B1A) + }, + { /* P{72} */ + W256(0x1F67006F,0x4DAA10A2,0xD2CAC6BB,0x1BBD786E,0x34EF1AAA,0x5668E51B,0x84ABC92E,0x76CE2370), + W256(0x6942F699,0x775B57C5,0x62952644,0x44DD2B3C,0xD6B3AD0D,0xCCC2E090,0x929D4430,0x3448386F), + W256(0x50B99804,0x2F971DB3,0x59461C34,0x1CEE220F,0x7B5586D2,0xF0AE8F96,0xCBB727F9,0x742CA51F) + }, + { /* P{73} */ + W256(0x40A109E2,0xA97D2D27,0x0C5ADE76,0xEF72A564,0x47F89224,0xB3153E4D,0xA9C2453C,0x0757179E), + W256(0x241A5382,0x0D4300BD,0x5E919492,0xA0309E32,0x1C896343,0x8D4B6E26,0xD576B0C2,0x0EAE2D6E), + W256(0xCB862B52,0xD6DFBA4E,0x1106ACEE,0x96868E97,0x86E7A06E,0x25641606,0x9FAE1824,0x6257151A) + }, + { /* P{74} */ + W256(0x2182D28E,0x6C99D2AC,0xEFAA861B,0x047A4911,0x971AEE9D,0x10593C99,0x87CD88EB,0x17202829), + W256(0xF6293845,0xD5393FB2,0xA3CBEFD0,0xE297EEF3,0x0E6D7860,0x5054C953,0xF5DAC84D,0x4849B391), + W256(0xCB38DBA7,0xCC291020,0x7E4405F2,0xC3AF4D40,0xE9008947,0xE74B6343,0x9C6676FE,0x0AE47713) + }, + { /* P{75} */ + W256(0x808FC0C7,0xADDC19FB,0xB97F1833,0x833F2820,0xD3527F9A,0x3CAE0E4E,0x193E98CF,0x38AE17A2), + W256(0x66C546D6,0x78352D6F,0xF767B9B0,0x6ACEF560,0x7943D1B3,0x8BFCB4A4,0x7CE7A57F,0x58F6A175), + W256(0x418194A5,0x9DCC21A4,0x460E3A36,0xDC49B44E,0x197DD7E2,0x7091CA3D,0xD8E367DA,0x3BB4DFBA) + }, + { /* P{76} */ + W256(0xB44209AF,0x12C0FF19,0x0B46DC9C,0x2BC53CCE,0x19CA4BCC,0x4A6A7C71,0x98F3D04A,0x5C11757F), + W256(0x20CC12B6,0x13ED0213,0xC82AEF76,0x3ADAD589,0x02AD8434,0x8DBAC085,0xE5D56909,0x1314F390), + W256(0xEBD6C1D7,0x26145F55,0x7FE3F892,0xA18896B4,0xDD90AB3A,0xE8DE0D1F,0x2453BD12,0x3D6C810D) + }, + { /* P{77} */ + W256(0x21980C7F,0x7D53625F,0x48E60711,0xEB61D5C7,0x6CF4DA80,0x733A560C,0x1102454D,0x1CCA65EA), + W256(0x9A758D78,0x0E0C5959,0x8649A297,0x1C89BBB3,0xC29AC6E3,0xB1AB7D29,0x0475FA29,0x326436E8), + W256(0x123B09E6,0xD0F89EDB,0x9FE8D47B,0xCF0FD49D,0x8C24F02B,0x4A9D6867,0x96DF0A45,0x3968DF72) + }, + { /* P{78} */ + W256(0x2BCA971F,0xE3BC39CA,0x9BDCF7AF,0x19E76DF7,0x2A65A57C,0xB3741495,0x4E5A0FA4,0x7E6FDF27), + W256(0xD9F7828F,0x1D8E23B0,0x891FDD75,0x0DA52D29,0x20971626,0x3895641B,0x06756E8D,0x4C5B05A2), + W256(0x9A392A60,0x3D16F130,0x814139D4,0xD588033F,0x65382C75,0xAA29B40C,0xE844E19F,0x10657167) + }, + { /* P{79} */ + W256(0x93B015F5,0x45DF1875,0x41C1CAAF,0xA4B41336,0xA362D173,0x7525F9CD,0xCE1EE76C,0x096B4489), + W256(0xF22F1FDA,0x466C16C7,0x4C8A69BD,0xDED7DF05,0x50D4BE1B,0xAAA47933,0x1AA0A635,0x5419A886), + W256(0x1F50992C,0x4922CA3F,0x1C926D3E,0xECFD2A63,0x783AFB74,0x2A958B98,0x10A0A934,0x5245B5E7) + }, + { /* P{80} */ + W256(0x0E6315DF,0x23E811AD,0xE2AEB290,0x0B650D05,0xA75D586C,0xB7BA0F59,0x5E1F4DEE,0x043EEDD4), + W256(0xC7073217,0xF6C147F2,0xF3AFD20C,0xC651B919,0x7041F802,0x258FDBFD,0x4F45073E,0x173C4FA9), + W256(0x928DF9C4,0x3D71EA60,0x3373562D,0x5B7E7806,0xA29552B2,0xD9B0514C,0x993CC472,0x1E2A7024) + }, + { /* P{81} */ + W256(0xD45C811F,0x601A0FBC,0x92EC0803,0x24B7BC7D,0x17D2407F,0xA0CAE62B,0x06225B26,0x5FCB43EE), + W256(0x3509FBA4,0x310509B9,0x05631B75,0x0D8DB376,0x52401C87,0x97DECCBA,0x11B2E773,0x044649F4), + W256(0x9598215F,0x0C0D24AD,0xCC36628C,0x1B7F9026,0x7016DCEA,0x338E2F55,0x5CC0E58F,0x0C8A1BFA) + }, + { /* P{82} */ + W256(0x5A498632,0xAD0E8D3E,0x6664C2FD,0xBC5472D1,0x9B093759,0xD8856491,0x1C6A902E,0x0EC4DCE3), + W256(0xA53B3119,0x0A7FB14C,0xAE58286F,0xAFCFD591,0x380EDD5F,0x75C643F5,0xC4BB9C9B,0x76023803), + W256(0x698035B7,0x902B8965,0xD5D7E42A,0x7948C088,0xCB0EE751,0xDE7471DF,0xCC9CB0B9,0x0976A7D9) + }, + { /* P{83} */ + W256(0x8C69BF9A,0xED893067,0x395A26FA,0xF6277CB9,0xB2423BC3,0xB1B45AE5,0x73B49B63,0x38D6FEA1), + W256(0x36C79869,0x5BB02BE4,0x13405DAA,0x0FE7B602,0xD83397CF,0x78E9E6AD,0x35CE3966,0x0E146C28), + W256(0x4B0725F5,0x91A0862A,0x60233A46,0x1E299354,0x331CD827,0x770C6408,0x04FA705A,0x0C3B6E0B) + }, + { /* P{84} */ + W256(0x681D104C,0x8DE703B5,0x1263CB45,0x3D2F7A59,0x1CE56C63,0xAE710C17,0xFCC3E6CA,0x6B857C7E), + W256(0x8B2801C0,0x79D256B4,0x3C400FC4,0x7E9FBEAC,0x4733BA41,0xA751AB1D,0xDD418ACA,0x09DE2BF5), + W256(0xEFF0687F,0x3BF10FF3,0xF1E37BA2,0x5EBAEA34,0x1D66034D,0xE49E6126,0xC3B242CA,0x5B466E2A) + }, + { /* P{85} */ + W256(0x47FBB842,0x137EEB67,0x60811A8B,0x79DF5C75,0x71F8C89A,0x5A2BA76F,0x3BC8FFC2,0x09952A56), + W256(0xDC7EF83C,0xA2A8CB4B,0x5F93C226,0x96B5C6FA,0x0664E3A5,0xD4EBEB1B,0xE5C6CF2F,0x409B4ADC), + W256(0x834350C4,0x44D53DB9,0xA5F505B4,0x89299305,0x5949FF2F,0xFB22FAA2,0x04657D64,0x69B968A7) + }, + { /* P{86} */ + W256(0xF3B83F1F,0x6C9CE663,0x9CE2AE57,0xF12E893F,0x32C4C3D0,0x04EFC972,0xE69732B9,0x5F58FB4D), + W256(0x5348092F,0x04676E04,0x6FB6C492,0x0EACBD68,0xA6D70147,0x56091566,0x5ACA06DF,0x62D7BFA6), + W256(0xE2407206,0x3963D9E7,0x785795E1,0x0EEAD76F,0xA63BF4FB,0xE134918E,0xD3447FF9,0x65E052AF) + }, + { /* P{87} */ + W256(0x9A105205,0x56626C08,0x4CA91191,0x6A68847E,0x0AAC0CD7,0xACC899C9,0x2FE2A51F,0x38FFE58E), + W256(0x7D397715,0x2DA20831,0x716771BB,0xB3A08734,0xDAB3B832,0x5E5EAF8C,0x02F0FEDA,0x735FDC72), + W256(0x843BCFE6,0x95242682,0x3C2FC05F,0x6CD54F0A,0xA8EA74AA,0x10835128,0x2EE8A03C,0x019812EB) + }, + { /* P{88} */ + W256(0x43495738,0x77257B3A,0xC51D872E,0xB8EA4BE4,0x703993BF,0x415ABAF7,0x987DF031,0x5EB64903), + W256(0x187C9965,0x5780874C,0x9132CA0C,0xA1C3F5F5,0x5E6AFD30,0x5AE60162,0x39C2A855,0x74EBFE78), + W256(0x4A608A8B,0x8A1C5144,0x8857DBB1,0xEC97A2F3,0x793F5123,0xA4EA18A3,0xE1F42817,0x42E2A9EF) + }, + { /* P{89} */ + W256(0xD77E277E,0xB5CE6F2C,0x72CF0CA0,0x3277A6DA,0x4815441D,0xA39DD9BA,0xE44F7D25,0x2CAE3BAB), + W256(0x6EBA994D,0x5B6E0A46,0x39936244,0x1C1E7168,0x9456F39E,0x648B80AE,0x45E72DC7,0x37298A12), + W256(0x1B1A6A67,0x2DF48B8B,0x625B13BB,0x66613C4E,0x8CFEB944,0x613D1530,0x599E09D5,0x78BF5DC2) + }, + { /* P{90} */ + W256(0x0104B715,0x508D0974,0xF497CB8A,0x40DA1307,0xED9C492B,0x4DBFF163,0x23943739,0x4BD7AF7A), + W256(0x409D02B6,0x28D96765,0x945A433A,0x2666F83F,0xA708399D,0x4B644B7F,0x566FB51D,0x1158FBB4), + W256(0xB0CCD019,0x4350A962,0xA9863F9B,0xC3308270,0xE057038A,0xD103FBAA,0xB3015D8B,0x745E1908) + }, + { /* P{91} */ + W256(0xAE62FE0A,0x1D965A13,0x6AE6B9C0,0xE4237E73,0xA13A16EB,0xD41A5B18,0x4E6C256E,0x3421A686), + W256(0x43DDCA02,0xE07CA9F7,0x73B5945D,0x0C61C726,0x03365CA0,0xCBC82731,0x2E1B8B3F,0x33B2AA2F), + W256(0x70FCE4D1,0xA4CAC550,0x4B9B5F95,0x21409408,0x2A1D42C0,0x1F5C791E,0x4764BF69,0x1E7958CF) + }, + { /* P{92} */ + W256(0xC787A659,0xBA9F9510,0x03ED5493,0xD788B543,0xB0A5569B,0x683B5FC0,0xC0FE3929,0x797C8E25), + W256(0x1330964E,0xD80DE638,0xE21238BE,0x420FD04A,0xA052A0B1,0x07A1B3E3,0xB9F68790,0x61E8F308), + W256(0xF1396F65,0x31BD7F2B,0x2419860B,0xB111846F,0x41030B36,0x87B636D1,0xEA50D463,0x30E41FCE) + }, + { /* P{93} */ + W256(0x119B232B,0x49D07989,0x352B78B8,0x7AF92508,0x25D656C0,0x29981276,0xC20DBF1F,0x23B4E084), + W256(0xEEF5658F,0x3F963735,0xCAF6CD78,0x9EE0DEBB,0x487F1590,0xFEAD3BC0,0xA2DA3BA8,0x70330BFE), + W256(0xBB29C84B,0x68618AEE,0x44F6B1AE,0x886C8D3D,0x38AF923F,0x55D8FBB7,0x0CD689DE,0x45838D3B) + }, + { /* P{94} */ + W256(0x61295FB1,0x84AC4FE3,0x7BED5A8C,0x1CDFD675,0xA88212DB,0xE99428BC,0x34EB0AFA,0x373E0B2A), + W256(0xCBBD642C,0x6AE452DF,0xE72F33E7,0xE5426167,0xC0C30398,0x4434CD39,0x16AC6121,0x33004DAD), + W256(0x707BDEB2,0x5B436C32,0x54093925,0x73F4492A,0x34121367,0x20F34A25,0x625DA7C5,0x3C15A2BA) + }, + { /* P{95} */ + W256(0x8A61C57E,0x86A977F5,0xBF8613F0,0x0E4069D5,0xB0D80789,0xE24A7E40,0x0B4F5BF0,0x0B1CEC76), + W256(0x1DC892A0,0xA413AF86,0x1BFCB0D1,0x4CF5CB84,0xC0DC4FDC,0x25C0F20E,0x50B64C66,0x0D65FCA5), + W256(0x5B05E655,0xEB413F93,0x3EF0CC03,0xE36B4C6F,0x0DF058CD,0xB256D88E,0x13722755,0x07ADCBA1) + }, + { /* P{96} */ + W256(0x2F4951DF,0x79D7AF89,0xAFA6EB6D,0x88A06EB5,0x24C568E4,0x5831563C,0xAEB26CED,0x66707A19), + W256(0x747396E1,0x6C1310E2,0x4CEDE7CE,0x0EE40062,0x2D45E29B,0x9A3D7602,0x3F0CF648,0x204CBD04), + W256(0x379E42AE,0x2B2454E8,0xF12C7764,0x90C8758C,0x65E7C6E6,0x6C5FD2CF,0xCF80A50E,0x289E7F37) + }, + { /* P{97} */ + W256(0x4708CCA4,0xA16C8426,0xE436AA70,0xB6980348,0x4600A6E9,0x4F2683D0,0x3E6F41EB,0x47095BED), + W256(0xEA0EC072,0x9A971F3D,0xCFF14F17,0x787A1C8A,0x49AA1AFF,0xE1F6197C,0xBC0551F0,0x24705841), + W256(0x135BE2B4,0x659AEEEF,0xFB75B6DC,0x6CCDAD89,0x6B16E15C,0x014F9D4F,0x03E29B5C,0x1E7B503E) + }, + { /* P{98} */ + W256(0x3FD31B95,0xBD217B56,0x4342853B,0xFD09FB02,0x4901931A,0x52ECC0D0,0xB46FBAD3,0x531F7220), + W256(0xC00BA975,0xB0E55E3C,0xC8225FB0,0x8937C6C0,0xFD60E6FE,0x00846F52,0xBF5AB08C,0x159452D6), + W256(0x5688F03F,0xC98DE446,0x0E6107EA,0x89FF073B,0x9BF173AC,0x3648578E,0x78073A29,0x3789DF68) + }, + { /* P{99} */ + W256(0xE03E12F7,0xB11D5529,0xDDF46F16,0x75EB970F,0xF885F334,0xBE1F0518,0x68E343C7,0x2D27012B), + W256(0xA91ECFFD,0xE90965D7,0x8234D517,0x63BBDD90,0x51719D88,0x9380DF56,0xC8F44A15,0x2D096724), + W256(0xE2CDC6D4,0x7267E789,0x3672F87A,0x714F8BE2,0xEA9B45D5,0x55CD7495,0x9943EDEE,0x1F9F9744) + }, + { /* P{100} */ + W256(0x9B58521C,0x5FCB17C8,0x6645C49C,0x7DCDA917,0x5917BD77,0x3136EFEB,0x3673C3C1,0x7D5EF8A9), + W256(0x8666DD69,0x7F6D6501,0x2780C2CA,0xB013D32E,0x3789882B,0xA607D0B1,0xB5554A65,0x6E693BD4), + W256(0x513DD959,0x6337649C,0xA7717EA3,0xF3489531,0x2E946717,0x0BBB78C7,0x814BCCE5,0x3357CA52) + }, + { /* P{101} */ + W256(0x3FF58085,0x7E720B52,0xEC6A424A,0x8FB70C10,0x3FCB64A8,0x925FA8DF,0xACC6CE63,0x437E113D), + W256(0x01FA6A5D,0x88C0114B,0x19004A46,0xC168D1CB,0x2E00CBC1,0x4D148F64,0x2441151B,0x58C5D1D9), + W256(0x4F3F6B4C,0xD5A8D662,0x951AAB88,0xBCEBDD2D,0xC2603ACE,0xADFD5E27,0x5DD3E15F,0x70EA3233) + }, + { /* P{102} */ + W256(0xA9684D92,0x9514265D,0xE74D2BBD,0x55419CF8,0x2948C133,0x34451D1D,0xEB44B9AD,0x2420B420), + W256(0x7D7D252D,0x7B9F2EC1,0x9A152EE8,0x49B2EB29,0x4E9359AF,0x11A954C5,0xB369BB94,0x2F4D538E), + W256(0xE2BB55BB,0x2CA37418,0x0BF6B294,0x5819D100,0x2832F057,0x9E192E13,0x2281B8A2,0x3B99EF9D) + }, + { /* P{103} */ + W256(0x56F4B677,0x792E12E4,0x0BD62435,0xE0E7DD51,0x621ECAAC,0x53A50096,0xBF8DD44F,0x651B2093), + W256(0x5BB90B64,0x7C34EA99,0x498827DD,0xED6B5C4F,0x7E0CAC91,0xBD2C09FB,0xFC3F6C76,0x2E87C003), + W256(0xCB39F86D,0xB9A05483,0x7E208EAF,0x396CAF95,0x92D84129,0xA49F69B4,0xF0AED850,0x5BD3CFDC) + }, + { /* P{104} */ + W256(0x1106F4C8,0xA81C6089,0x48EAC4C5,0xCEA547C6,0xB65A4461,0xBABC5E19,0x914405BC,0x1EDD6BA7), + W256(0xB7A10A14,0x512E6FB2,0x91FDE918,0xE5A5ED19,0x30352098,0x9C7AE072,0xA86BCBAA,0x7480322F), + W256(0xB0B208C5,0x67D298B8,0xFC05876A,0x16C79B83,0x1B09584B,0xF2D11CE7,0x6D0F2822,0x71867995) + }, + { /* P{105} */ + W256(0x78A0ED66,0x5BF82D60,0x9B62E796,0x897F84EC,0x351EBDDB,0xC93D0B6F,0x978DC6A1,0x2A530E07), + W256(0xCC5B4C55,0x25DF69AF,0x4B1E7B43,0xD299FDAC,0xDC8026EB,0xBCB7E7F4,0xF671A838,0x0F51FEE0), + W256(0xE051A08A,0xE3ABC271,0x43549C50,0x5E9C303C,0x6E751049,0x971EE5C9,0x0990FDDE,0x6AF8CE48) + }, + { /* P{106} */ + W256(0x85072941,0x0D2EC63E,0x7629E4DC,0xEF34D76F,0x3EEBA243,0x4D299FAD,0x1D0E272F,0x1C0C8BA8), + W256(0x7DE8947F,0x49AC8B60,0xE6B60D1A,0xA598DABF,0x262BF2C7,0x7FCD7397,0x8B05C98E,0x01417670), + W256(0x8786E66E,0x39098578,0xA155B485,0xB2ABCBFD,0x9C793F7E,0x1ABBEE0E,0x969224B2,0x493EDFAA) + }, + { /* P{107} */ + W256(0x7AD767F2,0x249E0A04,0xA3912F40,0x1311C2F6,0x3F0934DE,0x897EDF4F,0x1F5F9664,0x0109D1CC), + W256(0x36FD7583,0xC6DB180F,0x6A3F0D70,0xD9504D7C,0x6B2DC20E,0xE317B1C2,0x1E0C2804,0x0331DC46), + W256(0xCF2BAB83,0x213C7DA0,0x56F00288,0x72C760FD,0x044FF105,0x4E13D9F2,0x59EA9372,0x54C1C1F1) + }, + { /* P{108} */ + W256(0xCCFF195A,0xD9439624,0x04AA2DC2,0xA69A217B,0x77CDEBAA,0x7B581381,0x6C36F14D,0x727062C3), + W256(0xF156D356,0xE38363B2,0x1A7A6C40,0xE2FCA0EC,0x336D9CDD,0xF3236173,0x54708983,0x50F85285), + W256(0xF65BE459,0xF7067E62,0xFBB87C7C,0xE22AB98A,0x8127A332,0xCD2ABF42,0x41243874,0x474F259F) + }, + { /* P{109} */ + W256(0xB082F07E,0xBC2D1E80,0xA25756BF,0x368CEA6E,0x7AF12C86,0x53A67CB5,0xB385EF92,0x17186EE8), + W256(0x7895403B,0x3A022D64,0x3EAFD6D5,0xDF7178FB,0xC50D54FC,0x1BCFC70A,0x4569F3B1,0x36E9B22D), + W256(0xEE005D40,0xBB82CDB2,0x01DB4779,0xB99D5B39,0xAEF8C235,0x291F080B,0x4E3B4D18,0x5326C57B) + }, + { /* P{110} */ + W256(0xF01D5B98,0x0BFA2499,0x8EC91D4E,0xDDB2533F,0x1BBF5701,0x7168D7E7,0xC9FAFE4A,0x7D9E5AF9), + W256(0x7310593B,0x7AB3AB44,0xAE863030,0xAFC3FA66,0xDBD73272,0x45E5DDFB,0xC668CCEC,0x65401219), + W256(0x9B773F39,0xA57C099F,0x7940844F,0xF8F0223B,0x83AA97C0,0xEA7C8A46,0x50335D21,0x6860DDE4) + }, + { /* P{111} */ + W256(0x8A54D845,0x3F2358CD,0x2203028A,0x5E1CBB1B,0x11FD3994,0x63F1D822,0x4308D8AB,0x37401E65), + W256(0x07B41D27,0x1E9ADCE4,0x880A16DA,0x343AE381,0x4FC4494A,0x49B82BE4,0x2726AEC1,0x6FD66D34), + W256(0x7CFE6583,0xECA26010,0x63921D49,0xF981D584,0xBB516BF2,0x1B69D8D3,0xA669E323,0x461C28C6) + }, + { /* P{112} */ + W256(0x01C923E9,0xCD69DB0A,0xB2EC7A51,0xC095FCCB,0x15518043,0x6BD7C778,0xB6BDE853,0x0DA33C93), + W256(0x349903CD,0xF3BFFB0A,0x664C68F5,0x0362F6BD,0x7D7ACE8E,0xB75C72E1,0xC26DE303,0x12813206), + W256(0x4D21FB37,0x8E82EB86,0xD706FCA0,0x784E6AA7,0x7986F343,0xCE5C5019,0x86222C9A,0x749A29CB) + }, + { /* P{113} */ + W256(0xF14EE1F4,0x5698F7BE,0xA93C6B27,0xAF410069,0x2F72E02D,0xC3B2308B,0x0697A906,0x5853C9F3), + W256(0x23578DAE,0x2E289B15,0x71F6E01F,0xF7D9EF78,0x663AA29A,0x8D660848,0x9DC8931C,0x0FFAD667), + W256(0x93B961F1,0x0DA98E06,0x4EAB4629,0x12244EA7,0x4B3814DE,0xAA09AC0D,0x160E7061,0x10FB7F2F) + }, + { /* P{114} */ + W256(0xD952ABD2,0x759DA5DF,0xCB26C4FD,0x78203568,0x8637EFF6,0xFB64F1C6,0x084E0E5D,0x5EFBE968), + W256(0x96B7C16F,0xA9527912,0x63B993F8,0x742EA244,0x61EAE9C1,0x7235F335,0x7585A4AC,0x2E5EAC3B), + W256(0x91A749C5,0x1B726B38,0xDAB40E67,0xB5586AA3,0x580CC602,0x88099153,0xC51BEF09,0x3CC1AFA4) + }, + { /* P{115} */ + W256(0xACD6C32E,0x6F976A4A,0xCCF43AC4,0x305329E5,0x086F0CA4,0xFE7D4816,0xE2E9B1B5,0x007CF519), + W256(0x68F99EF6,0x3CE79C3E,0xD9E039D6,0x325B0AA5,0xFE49C5B4,0x82CF5B6B,0x1BC2886B,0x056E559E), + W256(0xE4FDF1EE,0x5A7DF532,0xFF4DA4C2,0x36F0DCBB,0x1F12517B,0x61CB3FAE,0xDEB2ECC2,0x5590F3AC) + }, + { /* P{116} */ + W256(0x806F5FDC,0x4172840A,0xE1C0A075,0x80CF2E21,0x491792D5,0x084594C3,0xF2D73480,0x3563A178), + W256(0x9452D82B,0x7CBD6B00,0xFD61AFF5,0x38C36968,0xDCC1B605,0xF1E876AA,0xEF44FF57,0x2BE54637), + W256(0xD94DF57A,0x2521D70F,0x38867486,0xC1166884,0xFE418AF3,0x35555E4C,0xD2B4FE50,0x5E7E4DDB) + }, + { /* P{117} */ + W256(0x42A5E164,0x863C1237,0x40FE626B,0xF8044410,0x5EE943C0,0x9EACA686,0x90EAA131,0x440BE3EC), + W256(0xCF866787,0x5913D7BF,0x5537B933,0x94DFD2A4,0xFE16E927,0x26E14EDC,0xC1E88451,0x15024E35), + W256(0xC56B7601,0x6E258350,0x6AA0350A,0x01142CEB,0x704EBD76,0x3FC64777,0x6C64969A,0x212D6D6F) + }, + { /* P{118} */ + W256(0x2270F29E,0x3F6A655C,0x77AB8171,0xAE2799FC,0x9F8A1E3A,0xFD162B36,0x90A5CE4A,0x47ECD96A), + W256(0x7409DC66,0x77A8BECC,0x9D3ED1D2,0x431DDD34,0x86E266F8,0xC62942FA,0xFF103BC2,0x46E5D5CE), + W256(0xA228B0B5,0xEF425960,0xFCC50DA6,0xBA65476D,0x3CB98B55,0x41739C39,0x2154E94B,0x0CAD13FA) + }, + { /* P{119} */ + W256(0x36820D13,0x9EE97BE6,0x70164070,0x2C08B8FF,0xFA54210F,0x6DE8F2E3,0xB360F28B,0x79107CEA), + W256(0x782D32C8,0x4C23EF35,0x4A46B57A,0x9767DDA2,0xD4EBA29E,0x72BD6514,0xD2EAC7E9,0x299A9AAD), + W256(0x86F7386D,0xD01AE2D3,0x219BB9EA,0xFFD4B450,0xA8774383,0x702D677D,0x5329101B,0x6FF36351) + }, + { /* P{120} */ + W256(0x7B3587A1,0x0E0C4745,0x91769720,0xC8421582,0xFE5627C2,0x91003F56,0xE85CA61C,0x6A2AEC01), + W256(0xA1A52002,0xFDFD082D,0xEAC7EA40,0x4CCD6F41,0x130B9C5A,0x22C95FC6,0x1FFB2792,0x768AC9E5), + W256(0x0063C3C8,0xEDB5A4A2,0xB73FD668,0xDB4937BD,0x22D13CF7,0xE2F7B924,0x503454EC,0x1778DB95) + }, + { /* P{121} */ + W256(0x7BD82D09,0x0F46D1AB,0x9E94D4AF,0x1A9308E3,0x09848426,0x589E4FED,0x750656D6,0x24B29DA0), + W256(0x6D03FFE7,0x9191F66C,0xB277C2B7,0x526D9AD8,0x0CA63F40,0x9198592E,0x70681952,0x5A850587), + W256(0x682446B9,0x4543AA9D,0xD95EE3DA,0xA6873BD0,0x05E3DA81,0x1352667C,0x17331E0E,0x728A4838) + }, + { /* P{122} */ + W256(0xD60A2084,0x77DDD129,0x8E3A7568,0x3BC7ADEE,0x8ED6ECD9,0x3D228C35,0x49D97F1D,0x54B5C9A9), + W256(0x5108C512,0xE8967BFD,0x2E2A9B05,0x74FB7C21,0x3A686776,0x7C9A0D25,0x0F17BF89,0x7DE8499E), + W256(0xE7EA37A3,0x9FE207C4,0x962C41D7,0x7F881301,0x582DF624,0x0DB13977,0x3C04302F,0x37BAA92E) + }, + { /* P{123} */ + W256(0xD6BB0652,0x6EB6315A,0xBB775227,0x94458890,0x239C7BDC,0x98FC0A5B,0xD4CCAB9A,0x599BAA3E), + W256(0x8ADCDB1E,0x266B206C,0xFCAA28D2,0x68C72F11,0x8C0AE8B4,0x16EB534E,0x9F0F7437,0x5C3DE1C0), + W256(0x33666249,0xDD43E25A,0x8415DE01,0xA4F8DD6C,0xABCC2DAF,0x5503235F,0xB80B04F8,0x2E43C2F7) + }, + { /* P{124} */ + W256(0x140E43E3,0xA3E3B738,0xC8F5A0DB,0x51847226,0xF9CA4102,0x3AB9407D,0x83005256,0x6DB8BB5B), + W256(0x2B9A38DC,0x1D5544CA,0xF0EC30C3,0x24B58309,0xF41BAB99,0xB8882607,0x48A09817,0x11DBAF2A), + W256(0x39E7695C,0x1538256F,0xB7290D01,0xE7E39640,0xD2582546,0xAA24A1EA,0x76A6AB17,0x1B0C351B) + }, + { /* P{125} */ + W256(0xB78294AD,0x7550EC45,0xFFAE747F,0xEE25B2B4,0xC8BD244E,0x65613F77,0xFF601899,0x544F0F82), + W256(0x0C0270A9,0xC68B1D07,0x986EA7DE,0x6681AE6C,0x5D0C0161,0xE8DCABBD,0x2E487553,0x5AA30E06), + W256(0x2D9B8E57,0x8E41DA8D,0x0728E94D,0x67A7574C,0xB69717B4,0x1B6310D8,0x18E8E439,0x338CC7BE) + }, + { /* P{126} */ + W256(0xDD00B10A,0x7EF87E29,0xA69E8401,0x46D7F7FF,0x5576BE17,0x10A99A87,0xF16E56B4,0x2BEABC55), + W256(0x6449EE75,0x868F3F7F,0x55B7A8AF,0xCD769000,0x8DB11E10,0x4ABCCA72,0x0AC3050C,0x2D193F9F), + W256(0x22824C89,0x7C5CCF47,0x07BAF05F,0xAA79B001,0x79F0E84C,0x05E488EE,0x62C70EDB,0x59CDA4E5) + }, + { /* P{127} */ + W256(0x33DA2FDE,0x404B413E,0xF66C3990,0xC3F5A183,0x6DFCF1A7,0xE33F99A0,0x22CC7500,0x541D736F), + W256(0x26BD487A,0xC8F25650,0xB1851D00,0xA80AC2EF,0x739ADCA1,0xE30BEA78,0xC6D25F17,0x13F5094D), + W256(0x4B9FF45F,0x67C7D337,0x5B287BB4,0xC49E7A0F,0x8E115FA2,0xB6F2A758,0xDA626D0A,0x66E18672) + }, + { /* P{128} */ + W256(0x193B877F,0xBB2E00C9,0xE0DC506B,0xECE3A890,0x36DE649F,0xECF3B7C0,0x98DE9E1A,0x5F460408), + W256(0x832FCEDB,0x739D8845,0xAE6BF863,0xFA38D6C9,0xB74FFEF7,0x32BC0DCA,0x14BCE45E,0x73937E88), + W256(0x297BF48D,0xB9037116,0xD4F06834,0xA9D13B22,0x4696BDC6,0xE1971557,0x91D5E835,0x2CF8A4E8) + }, + { /* P{129} */ + W256(0x955EC3D0,0x226343E5,0x9D175A1B,0x7EFC48D8,0xA18B1A3C,0x98385297,0x636C4322,0x5492BEA1), + W256(0x0D0EDBA7,0x6224329D,0x8E04A966,0x46778080,0x618D99F6,0xC62CE016,0x408F8D31,0x2F810078), + W256(0x9065F588,0xE9D5690A,0x35160408,0x68C463A0,0x9E8BAA87,0x2DB1CABB,0xFB39AE79,0x2E19E362) + }, + { /* P{130} */ + W256(0x40B81EDC,0xB131A877,0xC50A6E37,0x2529CCE1,0x3D86DF40,0xF87178C4,0x72690814,0x3AA294B9), + W256(0x083AC1C0,0x31746C23,0x1C3DB42F,0x3DAC7B51,0x228A9F80,0xD4F12B16,0xB1806C0A,0x40730AB9), + W256(0x0552A87D,0x152402F2,0x46352008,0xE69F2C75,0x3DA75873,0x09D51A51,0x428677AB,0x4E71CD08) + }, + { /* P{131} */ + W256(0xCD63A5CF,0x34ED76D0,0x1F9660CF,0x74DFC195,0xE1127868,0x54F23FF7,0x52D2D691,0x09EF2D3F), + W256(0x00004A14,0x9473F1CD,0x2D3E101F,0x7ACDB1FD,0x3F14D3B1,0xBADF67DA,0xDD5FA9B5,0x720361D4), + W256(0x07B12573,0x75E9D3EF,0xD4A699B6,0x07776372,0xB4D16DDD,0x25745C88,0xE7729DB5,0x2C42D3A4) + }, + { /* P{132} */ + W256(0x87A8ED1B,0xFB4FB8BF,0x3562C0C1,0xE61DFF95,0x2EB7C3F6,0x7E0099FB,0x8338B347,0x4BFD51DB), + W256(0xD66DABA4,0x2CB2FE4F,0x89AA7F00,0x10A18070,0x714AED31,0xB4F37238,0x4E9867F4,0x205B2E2C), + W256(0xBDB17451,0x3FD78085,0xEF06458D,0xF4AEAAA7,0x8C5836F4,0xC871854B,0x1115B50D,0x0FFD138D) + }, + { /* P{133} */ + W256(0x0AF1F0D8,0x9DF50673,0xB11F9B70,0x75535041,0x99EC8B4D,0xE8C33680,0x81CA5E23,0x250AD1F2), + W256(0x3E11BE9A,0x0580F7EC,0xC90A1D21,0x0973D59F,0x33E48155,0x9F32C03C,0x27B19D76,0x4AACA156), + W256(0x1577E699,0x03D16C21,0x8E5F2C2C,0x89A46964,0xC56666A5,0x86374D4C,0x46BB7004,0x741323B8) + }, + { /* P{134} */ + W256(0xA9B25300,0xEC4F3DED,0xD085E701,0xCBBABA10,0xA1518C1F,0xC24F4DAE,0xFA6EB46D,0x4DBE8C6F), + W256(0x04A28695,0x4091C103,0xB40DB506,0xEBA17E70,0xDD1102CC,0xF5BC279C,0x23C81CCC,0x16643587), + W256(0x43273AD2,0xA24E5171,0x44A356EF,0x60F47882,0xBB30B209,0x1E1754B3,0x82488C52,0x2DE4A5E2) + }, + { /* P{135} */ + W256(0xC7F31CE4,0x2FF8BA76,0x73599089,0x71CCB658,0x4B8FF7E3,0x5B79D720,0xD7E029FC,0x201E2DA6), + W256(0x9958D609,0xBBF5BBF8,0xE1A1359D,0x30981D35,0xB78D1571,0xE326CC62,0x4BB2DE35,0x154C89FC), + W256(0xA485927F,0x950868CB,0x99309DBC,0x5A65136C,0x69C7A60E,0x2EA9E9F2,0x7431685E,0x18F69D0C) + }, + { /* P{136} */ + W256(0xD78789AC,0x084ABC56,0x4C34A837,0x5659A950,0xC8E32D7B,0xFCBC29CC,0x13A35552,0x490BAD92), + W256(0xE038D4E9,0x9B3F9942,0x6CD96AA5,0xEDA655EC,0xF0B1D81F,0xB2A94883,0x3A65A94A,0x38639CCF), + W256(0xA7817C8B,0x2AF87C80,0xCD31C019,0x3290308B,0xA7BE274B,0xC389CFAE,0x10BFE889,0x6A125AEB) + }, + { /* P{137} */ + W256(0x3D24E162,0xE20267B6,0x68A6D572,0xCA586924,0x03ADC37A,0xD498C9E7,0x9BD5EB1B,0x202D4526), + W256(0x94AAEA83,0x67FF3389,0xDF086F32,0xBC661418,0x8278692B,0x4F6E34A2,0x171D88ED,0x3405D3A9), + W256(0xF3D71F71,0x0349F89C,0xD391896E,0x6C59EC91,0x60E3B489,0xC601B735,0xD16A68C3,0x37EEFB40) + }, + { /* P{138} */ + W256(0x3BA3C672,0xF56E4142,0xE9368956,0x573E3974,0xE7A5B7B3,0xD6A2DF8E,0x4A134A97,0x3147F866), + W256(0x8C5FB918,0x961CD052,0x645EBC80,0x8120A7A9,0x0F1E6013,0xD448452A,0x06AA1A4C,0x05D53ACA), + W256(0xDAED85E1,0xC6C34026,0xB2D4B1E0,0x3CFB0BD6,0x370B87CB,0x0F12416C,0xAA945A13,0x0224A2EB) + }, + { /* P{139} */ + W256(0xB7294205,0xE526547C,0x78F2614F,0x0B8E75ED,0xF001D89A,0xD06A714B,0x4EFA41C1,0x6AF7C939), + W256(0xFA893CC6,0x67FABBAE,0x849AA0E9,0x6701DB39,0x8BC4C43A,0x01718CF6,0xDC8B76F5,0x0E5F734B), + W256(0x3CB66A17,0x0540E82D,0x8D07D837,0xD8D957EF,0xD8C809E2,0x9BBD0223,0xC06C287E,0x57D04A0A) + }, + { /* P{140} */ + W256(0x7E348382,0x305C39E3,0x151F8FF5,0xA6961D62,0x3E75B0C5,0x9B3BA96E,0x41A21DA3,0x1185B2C0), + W256(0x080A91B1,0xE20AC913,0x7F570A48,0x1F5176F9,0xADD984B8,0x5ED8EA61,0x0FBFCFBB,0x79613D64), + W256(0x2A195A23,0x7211BDE4,0x61B1B2BD,0xD6B973D1,0xED88D400,0xBA6EACDC,0xF6CB238D,0x04C90947) + }, + { /* P{141} */ + W256(0x829F065E,0x7F39CA1A,0xB1AED2EC,0xBE497D51,0x44CF5F3F,0x7CD059B8,0x3DF51B03,0x69BCCD33), + W256(0x9BF83FF4,0x210A1FB2,0x0A04DA21,0x8A6A0F76,0x5F656141,0xF0C749BF,0xEB8BC7D9,0x00439D12), + W256(0x3D9E0C3A,0xAE9A651B,0x6D13FD33,0x0AB0D68D,0x035AB3A2,0xFE6951A3,0xC39650A1,0x29A6A9CD) + }, + { /* P{142} */ + W256(0x7B6B016F,0x39FD96E5,0x078B082F,0x5ABF92ED,0xFF012931,0xC905F0E6,0xEE141164,0x762D88A2), + W256(0xC8D474CC,0x2A6C73C8,0x4240C83C,0xBDD88157,0xBFB840CA,0x6482D3D9,0x577FA278,0x42E006C7), + W256(0x7B427448,0x2BC628BB,0x2E34AD6D,0xC30A541B,0xD6008DFD,0xBF692762,0xB43988BF,0x7BE4CBA5) + }, + { /* P{143} */ + W256(0xD185CAE3,0x0610B7C9,0x393E1EEA,0x22BCF7F5,0x50B5A498,0x078F20B6,0x75DABCA8,0x528D0C4E), + W256(0x7B7D5D33,0x1CBB13CC,0x897F473A,0x48C2338C,0x38DAB8C7,0x92D5A13D,0x92780AAA,0x73B88C74), + W256(0x80E27FB5,0x0F091F80,0xB49773AA,0xD839AA99,0xE18637C9,0xD83CCE6A,0x9C92E15B,0x03946587) + }, + { /* P{144} */ + W256(0xFDCDBA71,0x089F56A4,0x923939BE,0xDD032610,0xCD3FECDE,0x2FFD1803,0x2852B233,0x3508C355), + W256(0x0C6804C2,0x976AA014,0x04B12D0A,0x37C40803,0x1F0473FF,0x10287E28,0xDC487F40,0x3D2910DD), + W256(0x8C0E2780,0xE0156E4E,0x147B72AD,0x96963476,0x15F7D223,0x35D6E9BE,0x732F5BBC,0x7A8CE344) + }, + { /* P{145} */ + W256(0x9510C49A,0x49192B17,0x463D436B,0x8375825D,0x0BF30FBA,0x6F749404,0xFB3957BA,0x32A3650E), + W256(0x686D3B9F,0x875624D2,0xD010EC63,0x7D2508CC,0x0C70A6E4,0xE63EBB26,0x1AE53B8A,0x5A031778), + W256(0xD70C0232,0xE15D831C,0xFEF230E6,0x21810B5E,0x443CEC71,0x062533B6,0x3ED57767,0x7950DF2A) + }, + { /* P{146} */ + W256(0x237D9833,0xE6180436,0xEB38F533,0x525696EF,0x5C27BAC7,0x09B10FCD,0x3BA1B69D,0x608EA1CF), + W256(0xE717A6E0,0xA056AC6F,0x7B5F666D,0x00A1B311,0x79035A10,0x5E3C4492,0xFAF62B07,0x72C0E858), + W256(0xD207E130,0x07D035BB,0x50117EDE,0xAF7053B5,0x912C5C81,0xFEEC01C7,0x886E8D51,0x1A1FAC04) + }, + { /* P{147} */ + W256(0xF01E858E,0x1912EE7C,0x9ACD0FA7,0x592C8BCC,0x8450BDCF,0x753F805D,0x70AF3575,0x71BED116), + W256(0xC2B406D2,0x01184DF2,0x6F206147,0xF76B3C56,0xA3822F1E,0x57139091,0x793C5D31,0x5CC2B0D9), + W256(0xD85FD4B2,0x8F19FBD2,0xD4D2CE75,0x59F1A77F,0xC51EF80B,0x85A6259E,0x0C738FD2,0x7E12A2DE) + }, + { /* P{148} */ + W256(0xD34F712F,0x559AD49C,0xD8FB35E5,0x4EA4D1EF,0xF723BAAC,0x5909AD24,0xC4704F23,0x3183C84A), + W256(0xFE1998A0,0x4EC3D6C0,0x7FC3BCCF,0xB9BE0FED,0xC92A1F39,0x6F7CC86F,0xFBA3B48A,0x0A10C4DF), + W256(0x45995411,0x31FD07B5,0xC069D22D,0xC9FABF61,0xE0252BEB,0x766B85BB,0x2188A218,0x10E588A7) + }, + { /* P{149} */ + W256(0x82FFEF83,0x74D498CF,0xFECD2263,0xECE755A2,0xF493EF3E,0xC281538A,0xF2303FB5,0x54D171EB), + W256(0x563DD509,0xA63C9137,0x15C99B21,0xF7EFAE07,0xA6D3FC6D,0x64780364,0x51D6089F,0x1F331518), + W256(0x25C78ADD,0xB871CEB1,0x3C04C296,0xC0D7481E,0x3A0F2833,0x7DE88611,0x5B7672F8,0x6E1CF0A4) + }, + { /* P{150} */ + W256(0xBA0B03CC,0xE78948AA,0x58B6B3F2,0x46A3C561,0x1BE481F6,0x0E964066,0x8C25C3EF,0x3664E01C), + W256(0xA0A886B6,0x198599BB,0x876645F2,0xB6BD8FE7,0x8B7591D0,0x2417725C,0xEE1935D1,0x3A08AAE7), + W256(0x1534AF52,0xDC1CBF91,0xF7AF099B,0xF4FC0066,0x88137747,0x97397E9A,0xE80E74F4,0x349B9669) + }, + { /* P{151} */ + W256(0xEF471FFB,0xDD240E0A,0xA7856EF8,0x57702113,0xD957EF9C,0xB8E69C9F,0xBD3C4500,0x79ADD1B2), + W256(0x80847F79,0xD90137DD,0xBAF8BFDA,0x71D9AFFE,0x4F245BCD,0x8B749F1E,0xB2AE8BF6,0x642F1CF2), + W256(0x706C0E4C,0x9744E5E5,0x24FE9139,0xB0E8006D,0xC7E8AD1C,0xA69BAED0,0xD6FFB0D6,0x4CCB9693) + }, + { /* P{152} */ + W256(0x245D71BB,0x7E2177F1,0xE461CD75,0x4BED3A32,0xC81E1C67,0x48EFF412,0xBAF0A0E1,0x0759D1EA), + W256(0xAC5573A1,0x694F0A87,0x8D490435,0x86F3EDAC,0x69CC424F,0x8D05AA8C,0xD3C5308B,0x3285F2CD), + W256(0xCB0CA64E,0x615777A6,0xF5A307B6,0x4B2BCC26,0x819E835F,0x7E2A4B4E,0xD949088F,0x60A0D80B) + }, + { /* P{153} */ + W256(0x40DAAB62,0x033E6D42,0xD01BE421,0x07C1B46C,0xAD6293B4,0x826FF014,0x65A1773A,0x7D7BB82E), + W256(0x510D12E8,0xBE064448,0x9C8CBA8A,0x76AE88E1,0x591BE232,0x14357377,0x1B5D7B44,0x28A272D7), + W256(0x869E6F11,0xFE3AB0D4,0xFA8B0BFD,0xA5125FFB,0x453B4759,0x6B7075C9,0x2F32F6A8,0x0F03FF74) + }, + { /* P{154} */ + W256(0x3C94139B,0x97949B17,0x077870C7,0x24983AD3,0xA52B4D16,0xF170D9E9,0xD359BD78,0x1427C7B4), + W256(0x9DE5470B,0xC227D0A3,0x8F7B3712,0x0DBB9165,0x2C7FEFF1,0xAF2CE780,0xAE5534FF,0x60DF4EA5), + W256(0x98CE5195,0xD1536153,0x6A72C08F,0xA48EBEF1,0x39CF6449,0x4F621910,0x0A9FBF8A,0x0284779D) + }, + { /* P{155} */ + W256(0x0497BEDF,0x451E38F3,0x895E5DE6,0x24CF56E1,0x92B28E61,0xC2B0A79B,0x44ED80DE,0x47360AEE), + W256(0xD88C8292,0x04DEFEA1,0xB3CDD5DE,0x839768C3,0x52DAC506,0xE6ADBB65,0x7EAC3D52,0x1B7C8B7E), + W256(0x9E1212B4,0xB1A2C143,0x19527854,0x2A2101C1,0x604E4C45,0x2AAC510B,0xFE1736A5,0x61A9CC16) + }, + { /* P{156} */ + W256(0xB14F5809,0x79FD59E3,0xD56A8126,0x2267267F,0x2BBB00CB,0xEF28666F,0x70348032,0x04E64717), + W256(0xC1977F4F,0xE8E260C9,0x29041772,0xA0286C18,0xCB1F6094,0x38E868BB,0xA701F2D2,0x5EC36955), + W256(0xAEAE57D6,0x0F66A28B,0xCEF451D2,0x03629DE7,0x36D14CDA,0x261B2919,0xDC7D2447,0x61079D97) + }, + { /* P{157} */ + W256(0x9B8F0086,0xC2B8F399,0x9868469C,0x410ACE9F,0x0A12C56E,0xCD834C27,0x5D423DD2,0x004D7BA3), + W256(0x45813608,0x2A6177D8,0xE38DFFEF,0x09B400F5,0x805633D9,0x1754A95F,0x57E41E84,0x514113B9), + W256(0xDD05FA4E,0xDDAF0EA9,0xB53379A2,0xFC381A60,0xC2D4C1C4,0x2D0F18DF,0xE1897BF5,0x271FA439) + }, + { /* P{158} */ + W256(0xDCEBE6AD,0xE252270F,0x049EFC21,0x1E1D8802,0x8A4EAFC2,0xAEFDDEC9,0x0119A165,0x2F35657F), + W256(0xB3FFCA5D,0x7833FDA9,0x3C5CD47B,0xCD8F493A,0x18647670,0x3A68F5F4,0xD69044AA,0x57DEA19A), + W256(0x967ED429,0x4D255CED,0x822A1E3A,0x50651B4C,0xA0F56F58,0x9A93F1C0,0x2A033C0F,0x26DA368D) + }, + { /* P{159} */ + W256(0x4ED2FCBF,0x6416F27A,0x3A355DDE,0xE2B4CC90,0x6F7CBC57,0xD110663F,0x41497CCB,0x46C5572B), + W256(0xA7B1D798,0x17E813D3,0x6B76BCC6,0xF9A26A8F,0x31E5CA85,0x124C1BB7,0x8BBAEBD3,0x71B4D300), + W256(0x83EDE334,0x1FD1C0AA,0x85CB7B8C,0xFA257C09,0x96F02600,0x13CCC95B,0xC80C67B0,0x5EE86AEC) + }, + { /* P{160} */ + W256(0xF3FDDFE3,0x77102749,0x79BEAC52,0x093B1317,0xBABA54C7,0x2C1A5CC1,0x82ED20F9,0x7CC2EFFD), + W256(0x627C7B1C,0xFE5E30FE,0x8D82FC2F,0x7D6DE30D,0x1C1BF394,0x6B7981B1,0x955690EF,0x6EF79537), + W256(0x38AC1D9D,0x317BD4C9,0xD43A48C8,0x120B22AB,0x25BA47C7,0xD373691A,0xDDE79E2D,0x444F44EB) + }, + { /* P{161} */ + W256(0xD05F2D3C,0x7CA77213,0x0C380077,0x8A61A13F,0xC2C06C3B,0x3B6956CA,0xAAB52726,0x21EE01F2), + W256(0xB1F4422D,0x7AA57251,0x2356B185,0x210F8984,0x093E1544,0x8DB759F1,0x6CCB7827,0x0E520424), + W256(0x7210D454,0xE99CCC6C,0x8DBED73A,0x9278B219,0xC984A72B,0xC404D1C3,0x32746A36,0x14AFA6B5) + }, + { /* P{162} */ + W256(0x2BF4376A,0x6FF950EA,0x5B86DB4A,0x970D30F6,0xD2EE3EB1,0xFD04F109,0xB4B8924C,0x23654DED), + W256(0xAA496A92,0xBB24631D,0x560F5B8E,0x9A4DCCAA,0xFAD2D247,0x964C615B,0x65681C6A,0x0CF07C2D), + W256(0xD9512BC6,0x6B1E6C89,0xC7992AE0,0xFF307335,0x78620616,0x1E41B439,0x73477C30,0x5F5527F0) + }, + { /* P{163} */ + W256(0x366F2064,0x0F59397B,0x00FFBDFD,0xCA579E04,0x6DBD3E97,0x4627C074,0xEB010236,0x101AE639), + W256(0xDF923A45,0x72743E1A,0x1B73554C,0xA0BD821A,0x5CB5B0A0,0xA643C963,0x01173DD7,0x48EA9EAF), + W256(0x1472D9E0,0x42BF06ED,0x572013EF,0x6C5B1064,0x28F3A65C,0x71536C86,0x95C00785,0x0AEC3037) + }, + { /* P{164} */ + W256(0x843606BB,0x6CBCDDEC,0x1B031E0A,0x47208C7A,0x73C8628E,0x804710D3,0x8C6389BB,0x24767BCE), + W256(0x4DEAB9F3,0x5921911D,0xD2EE2C08,0xB29306F0,0x36213424,0xEBE05D52,0x487FFF46,0x6FC95025), + W256(0x52E0D95A,0xEAE74B37,0x01319900,0x88FC646D,0x6D6482B1,0xA4648C1C,0xC69F70C4,0x185EF4B1) + }, + { /* P{165} */ + W256(0x626330A6,0x07BB7B82,0x102512BE,0x290663CB,0x69FCC45D,0x35126923,0x70F829AA,0x6360F825), + W256(0x673DEA49,0xDA1C29B7,0x7ACDB58D,0x5C791FA2,0x691CD92D,0x5E538AAC,0x986252B8,0x19D69F88), + W256(0xADFC8D6D,0x82021D93,0x784C8063,0x9DD0FDB3,0xE64ADCCE,0x383F70A2,0x4333E288,0x5F391338) + }, + { /* P{166} */ + W256(0x9AD6DAD0,0x5AF51908,0x3F313DAA,0x3F696E0B,0x87370A41,0xC73864CF,0x0EF8379F,0x729D8F12), + W256(0x3C528CB3,0xFC02938C,0x139EAC04,0x8A0C04B4,0x6303418A,0xD580E5FB,0xAC77136C,0x58A3EF09), + W256(0x25CF504B,0xB13FA0DF,0x5187842B,0x787038F0,0xF3929B12,0xFC5E7DDF,0xCD706AF1,0x4D698742) + }, + { /* P{167} */ + W256(0xDBE7C0FB,0xF08F2F01,0x6B294170,0xEAB65C3E,0xF7D940DC,0x761EF854,0xAD5649AB,0x0ED7AD78), + W256(0xA94FABD9,0x3C18C4F5,0x5D4DECBD,0x09A0B15C,0x767627D1,0xD93CEF9B,0x7DFA8237,0x46B61CF5), + W256(0x12288FD0,0x4324E59D,0x5329A7B3,0x2CB47445,0xD9E94476,0x3B3AD463,0xA3243D8A,0x47BE3633) + }, + { /* P{168} */ + W256(0x6BD68F25,0xA3819393,0xFC692AA7,0x921A6473,0x102C552B,0xFBAAB570,0x0DA1E96D,0x22260E70), + W256(0xDBC441A8,0xD2DD61E7,0x3004A0F1,0xF5A113DB,0xF70504CE,0x49F05E44,0x3B07B9A0,0x2A59CD57), + W256(0xE116AB23,0x7D785536,0xE3FEE820,0x2D2FFA28,0xC62F75CE,0xF8D8FFF8,0x15C34F43,0x7626171B) + }, + { /* P{169} */ + W256(0xC7F57505,0xD6887915,0x22D43E1A,0x03F31B61,0x4C4C6736,0xEBA0ACCD,0x839A3696,0x028D5C21), + W256(0x1AA0566B,0x4C2B8A63,0x7DF7C625,0xCEEB045F,0x2BDA1196,0x5A5C972E,0x631D1AD0,0x6B8B1FB5), + W256(0x2D0CD5B7,0x855229F0,0xC0948473,0x5965AA97,0x7766CAFF,0xD7B3004F,0xFCBCC3A6,0x0D9D4EB5) + }, + { /* P{170} */ + W256(0x2C8CDC4A,0x2E9B3E1C,0x39292B8F,0xF301BDDB,0x6F45B448,0x908063DB,0x25C80DFF,0x03D2A9B1), + W256(0x72684FB0,0x3ECADB0A,0x18C4F682,0x6DDFB9ED,0x6DBBBAEF,0xA94247E4,0xADB3D562,0x2C63DF06), + W256(0xBA8DD8FC,0xFD788E43,0x5EB4E217,0x30FAE1C2,0x00568551,0xBD60C01E,0xF35C4364,0x066F5248) + }, + { /* P{171} */ + W256(0xD486EEFE,0x780D2DC1,0x64578DCB,0xDDF38E29,0x7430FBBC,0x1246A3AB,0xA8CD4997,0x4D86A09B), + W256(0x101AFA1F,0x9BF5440C,0xD49D4402,0x2FF63482,0x6E5AF731,0xE31EBEE7,0x417F08F9,0x3BBDF993), + W256(0x546B1AC3,0x441EA7B8,0x483A5D2D,0xF37D7E19,0xBA1E5334,0x00EDF00E,0x144B8647,0x2AA79702) + }, + { /* P{172} */ + W256(0xBD027592,0x32C35992,0xCA53E5D6,0x040CF4A5,0xE0463DD4,0x89B6026A,0x62F20B12,0x52D53FFF), + W256(0x8C16314B,0xAC40C7EF,0xC5723C00,0x9B3D64E9,0x2ED1B06D,0xE9D3DE86,0x62AD53D1,0x6F302028), + W256(0xD94095DD,0x174EEAB8,0xA5969D4F,0x613FF392,0x8E5A87B0,0x045D9A4F,0xA9223A7C,0x02B2BD7E) + }, + { /* P{173} */ + W256(0xB995530D,0x6881A0DF,0x4BED5FAA,0x6E83A1C8,0xA2C68798,0xDC3A5D25,0x7558CE6A,0x147ED190), + W256(0x762DD969,0xDB936784,0xD457BA9C,0x465BA33C,0x91EAF814,0x355491A6,0x4CCE2B18,0x7B1CAAAD), + W256(0x04FF82FF,0x72311A1A,0x63CB8D77,0xDF236226,0xD3F8974A,0xB5355304,0xF77D8471,0x7411C190) + }, + { /* P{174} */ + W256(0x064182AC,0x6CA9D966,0x49D1AA8E,0x1F3FB4AE,0xE1CFA08E,0x52D36BE5,0x8ADD0C82,0x1D5F5586), + W256(0xBE030055,0xD776B5CA,0xF8C69C37,0x912F1B63,0xBF914632,0x493AB77C,0xCC3CDA8D,0x748A0934), + W256(0x3E4787E2,0xD0A44507,0xDF698DE5,0x59559AB0,0x6859C01B,0x75D35556,0x11FFF4BB,0x0B3B867F) + }, + { /* P{175} */ + W256(0x69D85F9F,0x7EBC9686,0x93669D5C,0x73F25922,0xBC8C1531,0x0E003301,0x995C9C5B,0x711ADD89), + W256(0xAAFAB7AD,0xAD4A3101,0x684BCE24,0xF2957758,0xA594EEF7,0xA2D2CA0A,0xEFB47DF6,0x1089CBCB), + W256(0x91DBD7BD,0x031BF980,0xCE5D7DF8,0x516D988E,0x85288BE5,0xAB63762D,0xEEB64B4E,0x7E70E158) + }, + { /* P{176} */ + W256(0xC22FC777,0x8558038D,0x9D6072DE,0xF1D4EED5,0xE6005486,0x08290FFB,0x3DA24681,0x4A3A9AC2), + W256(0x2F1518F2,0xDCC797FD,0xB7963F13,0x619D3A39,0xF4A7A3B8,0xFFEE1A8C,0xB05FC1BC,0x35B6ADFE), + W256(0x94C5A6AB,0x4252EDAA,0xA251C3ED,0xF43C48BA,0xF4AE7037,0xF62E9831,0xB185B22F,0x0F5E3B9D) + }, + { /* P{177} */ + W256(0xA77B1206,0x04A3B229,0x32729905,0x73FDCA12,0x8C540CCB,0x5C40E645,0x27160146,0x486FB196), + W256(0x9F8877D9,0x6E4FA000,0x94DC3BBF,0x86AE024C,0x5FBF9C12,0xD8F74EFB,0xED93E8F0,0x7FA9E45B), + W256(0x9F91B00A,0xAA44B5B7,0xC8E0E05D,0x7191AADD,0x209AFDEE,0x381527F8,0x338CCBA6,0x6A143F29) + }, + { /* P{178} */ + W256(0x8EFE5F3A,0x535C23E6,0x6118BFAD,0xC95059E5,0xC89EE4A2,0xB4077EBB,0x3953B360,0x3A5905CE), + W256(0xB2EB2A77,0x02E8B328,0xA5A66D2D,0x23B9D06D,0x0F2C344D,0x0E778BC3,0xA2531B50,0x5C916EF3), + W256(0x96C8547A,0xC2EDB168,0xF32371B3,0x37284976,0x521BD71E,0x87F4FCC0,0x518D4D5F,0x25E95A25) + }, + { /* P{179} */ + W256(0xC59CCE86,0xA784CFBD,0xEFE84612,0xDE20DF51,0xD6D09035,0xC74DC0C3,0xC62F2772,0x1CE27D48), + W256(0x6900DB2D,0xDEB818F0,0x38DD986A,0xC3E266CB,0x5B65FF3A,0x1E22DF7F,0xD08609C2,0x6E3CDA36), + W256(0xEA68DB73,0xB67FE90B,0xA3A5B89D,0x31DE909B,0x3DF076F6,0x12E3020A,0x417F0AB1,0x6F329A5B) + }, + { /* P{180} */ + W256(0xEB9E5375,0xAA18E903,0x06B0AEBA,0xD02C3CC0,0xB5A31EA4,0xD3CE459E,0xD1DAE60C,0x570EDE91), + W256(0xC5C320D1,0xDC239AE1,0xF867C4E4,0xBC34B40D,0xB870C507,0x172D49E5,0x8EB1F1BF,0x033F1C73), + W256(0x79D70924,0x6D90FBF2,0x4F12E885,0x9E2843D3,0xE8F279C9,0x84C95865,0xB2593B63,0x3ACEE246) + }, + { /* P{181} */ + W256(0x7F00E7EB,0xA16CCF7C,0x5D2F2453,0x44D48A1C,0xFE858D77,0xE6A70EBB,0x00C3F6CC,0x1C7E8EDD), + W256(0x76F6F17A,0x5A4124F4,0xCA560CCF,0x5016EA68,0xC33B4658,0x74AA0A4F,0xB36D2380,0x5E5D38AD), + W256(0x3383A423,0x10E9863F,0x505CFA1D,0xEE18B967,0x90A3DCF0,0xEE2C2402,0xA9FFE46E,0x695425FF) + }, + { /* P{182} */ + W256(0x89DDA3DC,0x2CA6C190,0x41DC9EAD,0xCB471B4D,0xDAD19A35,0x871F7B14,0x8765CE86,0x68AEED64), + W256(0x88964A3B,0x5D43801F,0x63C01E8E,0x4729A1AC,0x2ABA8D3B,0x060B46BC,0xDD261858,0x1E0DF677), + W256(0xDF365E9D,0x7BD27536,0x06B14BF0,0xD1FD7DC4,0xCE4A5E1F,0xEE218B17,0x8FD166A5,0x78B98EEE) + }, + { /* P{183} */ + W256(0xE899A9EF,0xA7F04383,0x69457248,0xEA99F9F2,0xEB3C8884,0xB999D0C0,0x1C6A5651,0x71D2B090), + W256(0x5203596A,0x323E8634,0xC2CE6BF9,0x35149575,0x0A01DF70,0xB3424075,0xA34C1460,0x24BA40CC), + W256(0xB864D752,0x3A8695C3,0x8A15F21C,0xA918A66E,0xD8591BF3,0xB568E03A,0x349DCE00,0x71A0109B) + }, + { /* P{184} */ + W256(0x79F24806,0xBD431510,0x631CAB26,0x185162C4,0x7F839E2B,0x804D9373,0x4AAA443D,0x6C92E218), + W256(0xCFA352E1,0x3258FE15,0x5DA8A720,0x3729A963,0x36CF728A,0x094E2EE0,0x92288216,0x3CCE260B), + W256(0x8E60F089,0x6BDD1913,0x78BD3671,0xA496BBEE,0x9AD2F4FE,0x51CD5046,0x400836CD,0x5B4188A3) + }, + { /* P{185} */ + W256(0x2A0A8EC5,0x2E950A83,0x1E681A60,0xCB8F9932,0x52279D7B,0xDD9D8005,0x09C83204,0x14A74EFB), + W256(0x62318B07,0xA3733C55,0xE83EA099,0xAFD22928,0xD27D5C8C,0xEAA02A3B,0x235C0E94,0x33C2A00D), + W256(0x4B576DBA,0xB2946DD4,0xD8B53F91,0x21E413DB,0x2BE355CC,0xCA632A5F,0xCB961EDF,0x71ECBE0E) + }, + { /* P{186} */ + W256(0x545707DE,0x407AED1C,0x674278B5,0xD93C6610,0x309C6338,0x16B3BDDE,0x1125BFBF,0x41A4AB63), + W256(0x1764BAD8,0xA46DC40B,0x18D9BDD6,0x48A207E5,0xAC541818,0xB82EE200,0xDF85A2CE,0x3A1FF80E), + W256(0x9C9860ED,0xB2190243,0xCF7F2882,0x1613409E,0xC178472D,0x37220E85,0xAC8DBD3A,0x32CFB2AE) + }, + { /* P{187} */ + W256(0x29805697,0xB25E7710,0xCA8FB69E,0xD7CDEF18,0xABC42411,0x04C6DFE4,0x7CC589C1,0x778B5DB8), + W256(0x05AFC320,0x33438F9D,0x9FADD4DD,0x7A573360,0x3F1B9745,0xB7D73732,0xC77145BF,0x6BE47B8D), + W256(0xD61248BC,0x1F178641,0xC6CD5075,0x416D5A3B,0x46BA559E,0x879D3B34,0x0F83E801,0x72ED9485) + }, + { /* P{188} */ + W256(0x2D59F526,0x1638B393,0xAF1CE3E3,0x013EA2EC,0x4228D072,0x510A1FCC,0xFBB99466,0x388AAD93), + W256(0xBE203EA7,0x420CED3E,0xE565EBB2,0x64542DCE,0x0396360B,0x2114D04D,0x22EDAC34,0x07C5598F), + W256(0x80586512,0xFF6534D5,0xFAD70EC0,0x4FFFA5A4,0x2B0EB2C0,0xD4F1BB11,0x0F3597FB,0x506ED52F) + }, + { /* P{189} */ + W256(0x78638C57,0xE534A5A1,0x0CD5CA53,0x30EB2B0A,0xF9B39956,0xED53F11B,0x75581672,0x7C102DC8), + W256(0xA045F0CF,0x003C16FD,0xD76CD5CE,0x52CE729F,0x458A2035,0x3AC6C289,0x845CE344,0x26584C06), + W256(0xA6FA9A6B,0xE0404454,0x4792BAA1,0xADBD8457,0x2C58377B,0x6620EEF3,0xB0896918,0x37A562BA) + }, + { /* P{190} */ + W256(0xD44592E0,0x557A8B50,0x8142E64F,0x680E7764,0xC8265D83,0x3D778549,0x98101691,0x028CCAC0), + W256(0x2794FCA4,0x0CC1BC85,0x25A418A0,0xB76C830E,0x2C7D2445,0xCA12BCF6,0x2EBFD751,0x254DC753), + W256(0xD6F443BB,0x22FB9B36,0x83BEBC96,0x0FBD567E,0xE71352C2,0x07F1DA95,0x25B2AC21,0x7AF3B154) + }, + { /* P{191} */ + W256(0x85407E5A,0x8D12481A,0x7C7DA4F3,0xBFF0AF2E,0x1F78174B,0x4B529492,0x929CAF23,0x3A341284), + W256(0xB37EA56D,0x6DFDF91C,0xA6322508,0x844FE3D5,0xA01C7E92,0xCCCB3C9B,0x9CE2CA2D,0x0A1EEB11), + W256(0xB8DCE9D6,0xD14AFB05,0x2086ABCB,0x93612770,0x978A592A,0x28BD9665,0xF04DAB40,0x508171F7) + }, + { /* P{192} */ + W256(0xCD52CC12,0x8EF4F973,0x02FD31BA,0xBB0DF0E3,0x6FF47A51,0x5E14DF02,0xBE09D912,0x09867330), + W256(0xD63F6AC3,0x471CECD2,0xE006F7E5,0x0D189E50,0x7C53490D,0xC5D653D7,0x720A1D58,0x11994587), + W256(0x042830C3,0x159456A8,0xEC968CEE,0x4ADDE4BA,0xEA1F266F,0x1EECBE25,0x3CB564C2,0x28B6FD85) + }, + { /* P{193} */ + W256(0x0F77F81F,0x83C99A1E,0xB468D0E2,0x6210474E,0xE6C8C914,0x47F5C79D,0x930FBB04,0x1EF81E9F), + W256(0x40D54F15,0x54687519,0xDC0FB02A,0xF25DDE44,0xF03DD8E3,0xEF69233A,0xA1BB8F0D,0x118F2566), + W256(0x9341B419,0x578B7A8D,0x0957A946,0x6268CBE6,0x87AA2F02,0x935236CC,0x286055D7,0x2776A859) + }, + { /* P{194} */ + W256(0x329B2FDB,0x48143D7A,0xC223AA1C,0xBFF719E2,0x9C3A8DEB,0xB31BB4D2,0x634C45AD,0x0F8D065C), + W256(0xCCDE3BE1,0x4C9F1FC7,0x90C32EB4,0x24355055,0xE2D2F279,0xC580CAFD,0xC5E561EC,0x6F6C8FAF), + W256(0xA1722BA6,0x8A6CE79C,0x4D71598D,0x2E0E5271,0x7CD608EC,0xDD784D48,0x65DD681F,0x6D6A7605) + }, + { /* P{195} */ + W256(0x67D0431B,0x68D9F28B,0x9CF3A930,0xC76D2814,0x0D71BCB6,0x56928F21,0xBEAE381E,0x171C31CC), + W256(0x03AAFB2F,0xF90BCD5C,0x815934C6,0xD8F88081,0xF0D10CFF,0x1F78F418,0xD6871CAC,0x02A080DD), + W256(0x8E0FA607,0x8F144AAD,0x59157879,0x6FBFDA7B,0xAD515CEC,0x1A501EF4,0x2280DDB3,0x6B4088AC) + }, + { /* P{196} */ + W256(0x8050A9B3,0x969142AA,0x57911E94,0xCEFD6D4A,0x75B77969,0x3D2D1A07,0xE8D20F48,0x147F20FB), + W256(0xBE55CE98,0xCA043E96,0xB754AE8E,0xA6FAF419,0x184D0C43,0x4E7B4F8A,0x627E08B2,0x1F3E7406), + W256(0x6D195F8E,0x4260F29A,0xA5E9BA6C,0x74048DA6,0x25E1B139,0xCDC8F2C1,0x629DDBBE,0x038AB2C7) + }, + { /* P{197} */ + W256(0x7248E519,0x1F79EEDC,0x021DF483,0x6B3156E5,0x92559021,0x7B416790,0x0C02BB33,0x31CF66C1), + W256(0xA7DF6991,0x80641606,0x983C009B,0x16E4A154,0x33439B23,0xAEF405E0,0x3B59D939,0x38DBD5FA), + W256(0x4FA75AD0,0xEA714C2C,0xAD4BB08F,0x611AC296,0xB94F3A1C,0x7FC710EE,0x89A71DAC,0x0047A912) + }, + { /* P{198} */ + W256(0x2EEAE5B2,0xBC270AD5,0x88A30147,0x960205AB,0x77FDA1A5,0x83D7459F,0x9A174564,0x2DF4E051), + W256(0xC6892A5B,0x31235505,0xF1DFA44B,0x7A9BF56B,0xC5166795,0x741AF28F,0xE0ACFEF7,0x683D4E51), + W256(0x4D9F5CC8,0x21AFA244,0xFA1E2E70,0x703C9308,0xC54D90DC,0x9F846432,0x2671BD0A,0x6F0FAB9F) + }, + { /* P{199} */ + W256(0x8B6D507A,0x9306EFDF,0x24A4A4AF,0x8A858E58,0xC3AE6195,0x8D5239CD,0x128D97AB,0x7378CCD4), + W256(0xC37E5D11,0x685B27DC,0xE6053657,0x5A9823AF,0x87C245F4,0xA7AEE368,0xD4DD09A1,0x5F6B1088), + W256(0xF5BF02F1,0xA06ACCF6,0x4884CE04,0x0D077178,0x72FB231D,0xFAE1F25B,0x9D8846E3,0x49DAF881) + }, + { /* P{200} */ + W256(0x7C4AE902,0x474BD681,0x43A99BF3,0xF002198A,0x64DD2E2B,0x8DFBC6BB,0xC02C6D59,0x2254069E), + W256(0x6DD1C7DF,0xFDECFCFB,0x0A18991D,0xD91B028B,0xC4D0CD0E,0x74E4247F,0x5B8B5ADD,0x2F95C694), + W256(0x1F7A3922,0xABED4139,0x63649DC3,0xB6A36833,0xA91C5E11,0xAA21A8B1,0x6D6027C5,0x2D9CF438) + }, + { /* P{201} */ + W256(0x24388BC3,0x50468B76,0x087E73D2,0x851CE5FD,0x191C2AED,0x36AE4762,0xB011A87A,0x0A60BBE0), + W256(0xF225F04C,0xAD19CFCA,0xDEAB77A4,0x845DFF33,0xFDCAAF08,0x0D9FA0BE,0x841EFE92,0x5E52EFA6), + W256(0x4C7DD5C8,0x4545A8C7,0xB14A069E,0x5BF56FFF,0x86429545,0xC76C1AF7,0x3055A690,0x670C07E9) + }, + { /* P{202} */ + W256(0x44B91294,0x8F9EB100,0xE1542FED,0x67478749,0x535DFB48,0xB29B469B,0xE2E25F76,0x264A3066), + W256(0xF83F9EB8,0x0CB27F60,0x8CD82B0B,0x56ADFF6C,0xB03FB08A,0x037CCDA8,0xD2CF0873,0x42183695), + W256(0xA872B3A1,0x0B717AC4,0x3D88D1B6,0xA15A62D2,0x26D780DA,0x922E4324,0x6E905FE5,0x732113B2) + }, + { /* P{203} */ + W256(0x7EBBFBB9,0x1FF3A45B,0xD1282547,0xA8D86BF7,0x1BE1D08C,0xB0D70C8C,0xB21D19ED,0x06D2A8CF), + W256(0x340A1440,0x254AB26B,0xB7FAF723,0x3B55DB81,0x6F1B0DB0,0xD46C2720,0xD54F357E,0x78EFB14C), + W256(0xBA181D54,0x68E9BD0E,0x3D5A5AB0,0x13B4D6BF,0x0EAE1FAE,0x00B66EA2,0xDBE5E1BC,0x265D02EE) + }, + { /* P{204} */ + W256(0xB50C5365,0x2A0DF4F8,0xC691A617,0x804EB0A8,0xA48D86D7,0xD243F6CE,0x27F6FE1D,0x16276E24), + W256(0x7A6C53E4,0x4992E44E,0xAB8B7DE2,0xA53FF2B1,0x165AD0DE,0xCD0AAACD,0x608625E4,0x30F58C44), + W256(0xB5136309,0x866D31D0,0x5593D3BD,0x7E074B40,0x1F16AEC0,0x29C71C28,0x573FB2F2,0x2EBBACAE) + }, + { /* P{205} */ + W256(0x3555106D,0xEDC5296F,0x8321A7E2,0x4D434B2D,0xE894362E,0xC0070068,0x6D6B4542,0x6582A961), + W256(0xFB09C2A0,0x213E29A3,0x7508A69A,0xB609D379,0x350AE36C,0xC18C2EBB,0x2B4BD901,0x1E187F5B), + W256(0xB07EB9CA,0x6D2241CB,0x6F5E89CE,0x49644E09,0x738C0D4C,0xC54D97C8,0x4AD173B9,0x53FE0D2E) + }, + { /* P{206} */ + W256(0x71B8EED7,0x97F3291D,0x4789E136,0x18C9E991,0xC8CDAACA,0x08550516,0x88719EFD,0x05395EC3), + W256(0x2690EF5F,0x8D59447D,0x8D9006D4,0x7BBBE17C,0x0E7A90BF,0xEF233017,0x02F22ABE,0x2A748B93), + W256(0x3402CA3A,0xBBEAA6FE,0x97BF31CE,0x5FAA5A42,0x029BAADC,0x15B0D145,0x1E21F9F4,0x5B892389) + }, + { /* P{207} */ + W256(0x9AA4B0D6,0xAF367522,0x761EE007,0x20C3BE00,0x6338301C,0x03EF1816,0x936BD202,0x47BAB7A2), + W256(0x7BB8E420,0x3B1E3A0B,0xB63A34C1,0xF05B0CBB,0xF7980BDA,0xAAE01AE4,0x409046B7,0x64B18FB2), + W256(0x432FFE0B,0x0DFBF734,0xEC8DDD34,0x3DBEE455,0x66EF9396,0x4A74149F,0x5ED6E73C,0x63A250D1) + }, + { /* P{208} */ + W256(0x8128F86B,0x98E51B90,0xE6DD7E30,0x263F13E5,0x9689B811,0xD06ACE31,0x4F23EE94,0x57329348), + W256(0x1A4756D4,0x024FCFF5,0x6B882E91,0xB020630A,0x2075F533,0xB5D5F703,0x78B94DE6,0x324509D0), + W256(0x62140EA0,0x6775CD99,0x365B3EF0,0xD642D377,0x3F65CB56,0x601901BA,0xCF83F05B,0x2B939509) + }, + { /* P{209} */ + W256(0x6D6A253C,0x7E5E99FF,0x30A1733C,0xD97F397A,0xAB987888,0x670E3805,0xF8852227,0x030D83CB), + W256(0x6E1239E2,0x8B92FEDE,0x161B082A,0x71ACFF21,0x84B89C7C,0x237048D2,0x65C1D212,0x0AE59618), + W256(0x8FD54819,0xD8DAF9CB,0xD693E577,0x39E291D5,0xABC8FCC2,0x182476F6,0x20B3E13A,0x4D40AF27) + }, + { /* P{210} */ + W256(0xBF688F75,0xA1F94B8B,0x4405CC0C,0x77FB6190,0xC85681AA,0xAEF8D012,0x8B9E8DEB,0x745C2F62), + W256(0x264A3EE3,0xDD4F3641,0x75FDE909,0x66835F13,0xD6B2E022,0xB54A1863,0xF4BA14FA,0x5B427CF0), + W256(0xA292DB19,0x7077EA22,0x44A509E2,0xC78565E5,0x5A325BAE,0xBA708AD0,0x92E8D98B,0x08B85FE9) + }, + { /* P{211} */ + W256(0x3C2A3FC6,0x1119EF6D,0xFD6996A5,0xD5FF6C26,0x0B8A76D4,0x77B8CBB2,0x31E72E57,0x5EFFD1C4), + W256(0x301D8692,0x3C5098EE,0x8281B7F5,0x3AAA542C,0xA0C369E2,0x218C79A2,0x4C179097,0x6419A7CA), + W256(0x59C60441,0x18EA4F78,0x99EA645C,0x7B83A616,0x67151F89,0x8EF0FB59,0x894AACE6,0x5E39C0A8) + }, + { /* P{212} */ + W256(0x53BB5DE7,0x0739FB15,0xBD9B28AE,0xA216864A,0xBA0679E8,0xFB9AD874,0xC38FB07C,0x2218CBA5), + W256(0x7CF82652,0xD6AC0CA8,0x6C7FAE03,0x57869CD5,0x2D89124E,0xBCE83209,0xC4C878E1,0x4DF95D3F), + W256(0xB5927B72,0x59F7733F,0x61D984C5,0x6BE2FEA3,0xBAE6BFE3,0x0DFDF83D,0x86C56E0F,0x212806BE) + }, + { /* P{213} */ + W256(0x77C9B45B,0x2E28325D,0xE9846205,0xDF743DF4,0xA85F1015,0x85601B41,0x5E52839D,0x725C2A23), + W256(0x2640B516,0x087B45FE,0xE44C0B2B,0x6150594D,0x707E28F4,0xBA23332A,0x870E6B6B,0x3D262BB0), + W256(0x02400F16,0xA5585EC0,0xA7FC7C05,0xCD8E00ED,0xF56D3635,0x5AEAF2B1,0x4D374520,0x55DEFAD8) + }, + { /* P{214} */ + W256(0x03FDD76A,0x8DB456D8,0xB283770C,0x5B9E20FF,0xB98218A6,0x26FE8032,0xFB32B99D,0x2F6060DD), + W256(0xB5788D49,0xA26CB9E5,0x049962C5,0xA71302F4,0x564A2C87,0x2452441F,0x3FDFC76F,0x1A7D4AA3), + W256(0x009052ED,0x28072A25,0xC3C8EAAE,0x9A949B5D,0x1CCFDD1A,0x6B8C4C5C,0xE7D97235,0x7D80EA9F) + }, + { /* P{215} */ + W256(0x1AB2966C,0x3A8A63CF,0x6B8E081E,0x21390040,0x0FC10C06,0x75CD30FA,0xBAF97E6E,0x753E0BBE), + W256(0x9B2594BE,0x8D82476B,0xA6B5C9C3,0xF40F7B1E,0xA37A28D4,0xE21F8B31,0x89C5E37A,0x1FB2AF1A), + W256(0xB9D8A7A5,0x99DBC21E,0xE18019F6,0xEF895A84,0x0C75CEF7,0x4E2DFE2C,0x1778AB0F,0x5BE903EB) + }, + { /* P{216} */ + W256(0x1AE40D9F,0xCA7012D2,0x30854715,0x9871980F,0xBB143A88,0xD11CCC26,0xF56EC92F,0x66DFF11F), + W256(0x438ABF0A,0xA10B7043,0x5F23E52C,0xB0D19E86,0x3F32327C,0xB4199F0E,0x2C4E9F71,0x55EFB013), + W256(0xA0438592,0x1B583AA8,0x3EC1BD80,0x45CA9CDC,0x6283D900,0x146AA005,0x5FEA8E37,0x3D4C06CD) + }, + { /* P{217} */ + W256(0xC6427729,0xA864C021,0xA8FF6F61,0xD47A8465,0xBEA8CF54,0x307E2D76,0xF1E6AA68,0x3989530F), + W256(0x0C07DCB4,0x3A7CA532,0x555EA8BD,0x594847EB,0x9291248D,0x49B68908,0xF3238C74,0x52542CDD), + W256(0xAA940777,0xC8A55DBD,0xF602D143,0x84FC512E,0x7AFD5A3B,0x5837062A,0x2C32672C,0x7C3601CA) + }, + { /* P{218} */ + W256(0x2A98B263,0x8EADBC06,0x4ECBBEA9,0x134752D9,0x674D813A,0x3808EF6A,0x8EF4FC28,0x1439727E), + W256(0x7A068932,0xF05C508A,0x5073D890,0xD1E9F2C7,0xC75E6DDE,0x54748A79,0x4C059128,0x307685C7), + W256(0xC15DAC95,0x4FE76DC1,0x8C08202D,0xCEC2C534,0x0A41138A,0xF1476E54,0xE3E1D667,0x35961D0E) + }, + { /* P{219} */ + W256(0x9B209918,0x4BBF1D5F,0x45B9707B,0xCC66599F,0xE8027A49,0x6836ED77,0x58725C1D,0x14FDF6A6), + W256(0xC5584125,0x7035B550,0xA4396714,0x47CADBFD,0x842F7962,0xF5E3D12D,0xEAE771CB,0x5BBA73F7), + W256(0xD88B7241,0xBE0FCDF3,0x12C1C616,0xEF43E3EE,0x9520131E,0x242CE337,0x5142263F,0x780900A8) + }, + { /* P{220} */ + W256(0xEEC0B00A,0xE15B351E,0xF40560E2,0x05EBDE80,0x4BF3D79C,0x54FC1531,0x420E3B9C,0x25ACF601), + W256(0x3B286403,0xF607D3A5,0x1BCBB5A3,0xDF4CAC2D,0xA728DE9E,0xC3F2619C,0xD4610144,0x4E6BC727), + W256(0x9FE2D6FB,0x1C635C8C,0x8D4C5E93,0xE7045E08,0xD4DBC6AC,0x1FEC2422,0x2CF86CB9,0x7A66CD4C) + }, + { /* P{221} */ + W256(0x3650EE88,0x6B03097A,0x49AA5C27,0xD648B909,0x2EACCA57,0xA71404FB,0x1D0B2598,0x0B3E2F2E), + W256(0x429B19A0,0xD5C62B19,0xEDB7FBC2,0xBE74D35B,0x1501B39C,0xCB5ECD51,0xCD68F30C,0x520AFA73), + W256(0x9B94F78A,0x13D10D7D,0xF275FCEB,0xDD41952C,0xFAF7428D,0xD07381C1,0x554E6426,0x5F35320C) + }, + { /* P{222} */ + W256(0x42498232,0x1D5FBB2B,0x64617B01,0xAF964CD7,0x683F21E0,0xC73BD158,0xC6A76A1F,0x3F5BCCC5), + W256(0x90E427F3,0xE8698232,0xF566E95F,0xC6B82BE5,0x3AB95DD5,0xC5515D07,0xD23B78D7,0x7FD106BE), + W256(0x3F0206E9,0xBE1AF04A,0x81AAFADD,0x2A63D678,0xC0797D2B,0x28AEC8F0,0xC1CDF03A,0x5E60065B) + }, + { /* P{223} */ + W256(0xE1A07256,0xAB40F73D,0x1DCA0BC8,0x53070930,0xCCE7012D,0xC0CF5CE6,0x7DB88CEC,0x382861FA), + W256(0x8F6343A8,0x2628F9CD,0xEC504B17,0x9A9D3259,0x211E7AA1,0xEB95F901,0x0CE7A6B4,0x2A3C2862), + W256(0xB50D49A2,0x1FC22389,0x598CE6EE,0x016C7980,0x766BDA55,0x1D36F19A,0x1A3397CD,0x0EA73A03) + }, + { /* P{224} */ + W256(0x921F8AAB,0x3D34E768,0x6EEE4795,0x3746BEA3,0x59FA3CF7,0xEE02D1AA,0xDAEF126B,0x3273E234), + W256(0xD35A83CD,0x5740CA72,0x01ABEA1B,0x0CDE0160,0xECC21B16,0xFB7A7F6A,0xB048AC23,0x01BF2D13), + W256(0x71CE9AB2,0x3C4A8BBA,0xB61C7208,0xF73C2EB3,0xB8F9E211,0x73859EF5,0x6D310CF1,0x6A321B74) + }, + { /* P{225} */ + W256(0x67109E02,0x604E1E04,0x08F2D4B9,0x8085E5ED,0xC9753421,0xE0B5D551,0x3FA55DB6,0x5F89495A), + W256(0x87E6E9CA,0x75D6C8B4,0x036B42C6,0x843F057B,0x0CBBB0CF,0xB93110BC,0xEC836A5D,0x142A78F8), + W256(0x9EFE3033,0x5092782D,0x989329D1,0xD22832A0,0x30F98D17,0xA47C5891,0x8B27A411,0x0C8A1651) + }, + { /* P{226} */ + W256(0x2D02E7BC,0x8C7BAE65,0x0CF6B274,0xEA3FA9EE,0xCB7CF44D,0x2380CE11,0x2CAE4701,0x0D4B1E8E), + W256(0x9E42A45A,0x6BAC21A9,0x951EAFA0,0x30E796DB,0x2D65766A,0xFB9BA2D3,0x70457FA6,0x61C09DE2), + W256(0x0C9487B9,0xC8A7D67A,0xFFDE5271,0x485058E7,0x900E3D73,0x8D4C7C77,0xD77CE7FD,0x65FBB4FA) + }, + { /* P{227} */ + W256(0xA7A629E8,0x2133F962,0x79A0D1B5,0x5C9CB549,0x065F8C08,0x73904BB0,0xFAD0E729,0x4C4ED976), + W256(0xAA47117E,0x51A01FA8,0x024B909C,0xB2EBBDB0,0x5A972DF4,0xEA98D10F,0xE0A11B75,0x67C48354), + W256(0xDBF660EF,0x3A993910,0xC8DA689F,0x45E54784,0xBD91EF05,0x7BB3DE28,0xCCF3B029,0x402FF4EC) + }, + { /* P{228} */ + W256(0xD6230EBB,0x1D35D625,0x52DB2B63,0xD6337703,0x49D27E43,0xEB986558,0x222E4495,0x6DFE341F), + W256(0x08B7BDBC,0xC69F489B,0x83679268,0x77812954,0xC79B057C,0x8E7DB0BA,0x38DAAFE8,0x516F4ADF), + W256(0x063D2B1E,0x1252DDF7,0xECC83029,0x3BBAC44D,0xD75B2461,0x35B88786,0xBC3FCD97,0x67A510B7) + }, + { /* P{229} */ + W256(0x76E5A91F,0x72B274BC,0xE4E2FB58,0x740896FD,0x4398D057,0x3DB49CBC,0x67BF7C11,0x27877B97), + W256(0x249AD55E,0x2AA0FCEB,0x1EDDD923,0xA6F928ED,0x43A7F8A7,0xC8E42402,0x5403A69A,0x615D6EEB), + W256(0xE331CEF9,0x1AD54899,0x6B042736,0xCBC382F2,0xD766BBAA,0xC1FA864C,0xD8807D0B,0x1BD72747) + }, + { /* P{230} */ + W256(0xD41947D6,0x5A0EE465,0xD666A96D,0xB9280AF4,0x481E9302,0xD511A413,0x2085229C,0x1F446D47), + W256(0x87182E8C,0xF3F6BDF7,0x4EF9320D,0x1425737B,0x82810BB9,0x6C45A7BE,0xA27D07A6,0x3ABE9D28), + W256(0x3DC9C9D1,0xA797B1F7,0x6557305D,0x8779591B,0x86CA651F,0x5D50C612,0x570C11C1,0x25A59857) + }, + { /* P{231} */ + W256(0xEFA598FB,0x30CE8AC0,0x9FB323F4,0xD4BC57BE,0x25E14200,0xCD8AB81C,0xD81FE2AC,0x51311426), + W256(0x8EB09162,0xF43FF7B2,0x4B73FD5E,0xFA5B38C3,0x9017C42B,0x6A23D0B8,0x0CFD6207,0x455BFC85), + W256(0x67D08476,0x63B74D58,0x59B9F88B,0x3132DC57,0xD1C53732,0x01AEAC8C,0xFB5116B1,0x4F799CB2) + }, + { /* P{232} */ + W256(0x0A37B21A,0xC22D0128,0x70D97402,0x49ED37DD,0xD66B2847,0x3D37F157,0x0AEC3F5B,0x6A2B356A), + W256(0x71AF1BBB,0x39680D77,0x466DBA37,0xBA9EB095,0xD8E2A8AD,0x381319B3,0x21E7D92D,0x64E6A9AB), + W256(0xA2CC3D15,0xE63DC0EA,0x3CBF1FA6,0xB16BEDA7,0xF673E230,0x1C68E13C,0x416ABA4C,0x7966A776) + }, + { /* P{233} */ + W256(0x3D82DA00,0xB558ABA4,0x1AB1358B,0x47D3988B,0x7929EBA2,0xA1983740,0xD0BA5596,0x2FBADD1F), + W256(0x3C7ABD11,0x787D7303,0xCF018842,0x69196D20,0x7FBAFA24,0x6F050716,0x83651BAE,0x066548FF), + W256(0xCE0F5195,0x07BC0BBF,0xA136C3B4,0x3B4A0144,0x877423BC,0x13FDEF15,0xA9A62435,0x15B8D97B) + }, + { /* P{234} */ + W256(0x439B69A5,0x10842629,0x14F24042,0x23EAF650,0x6E0B55DF,0x9587F46C,0x1E1543F4,0x7CC8E271), + W256(0x74252CA8,0xB6B9DA76,0xA9C3ED11,0x5299EC18,0x0FD15B94,0xF6A7059D,0x8E8DE417,0x0B39D342), + W256(0x7356040B,0xCF729D4E,0xB3A71F12,0xA187A711,0x876626FD,0x017FBCCB,0x314C6E1F,0x4C62D119) + }, + { /* P{235} */ + W256(0x929993E0,0xF6E6C5E0,0xD0ACF6A2,0x848D3E2E,0x7BE75B7E,0x9CADD048,0x9872704B,0x05D76FDB), + W256(0x415F92E0,0xA067F291,0x866A63D5,0x8213233B,0xDBB61C6B,0xA310BD28,0x4D19886E,0x58C7F658), + W256(0x18432A70,0x0D9C95C8,0x6FBDED5B,0x7B43333F,0x032F2BA8,0x1A86ACB8,0xB3C5E5C4,0x1420E549) + }, + { /* P{236} */ + W256(0x53DCE318,0x6462D6A7,0xF7B16DF5,0x24D923D6,0x02A99281,0xAD2E2E76,0x277FBE41,0x2E6DBA46), + W256(0xF3CF928F,0xF9B31CEF,0xFD306987,0xE330D91A,0xBC042D05,0x2C212C31,0x414D6A2E,0x27414B23), + W256(0x413B240E,0x80C26D33,0xA0B89246,0xA53193AE,0xB2EAF649,0x4E1A8487,0xE3B4C292,0x12082216) + }, + { /* P{237} */ + W256(0xF2E69EF1,0xFF3F7F45,0xE2AD789C,0x5504F08F,0xAA245200,0xB0FB7E50,0xC6FE94E0,0x166F05BD), + W256(0x01805A82,0x1F29FAC8,0x66A06CFD,0xA4FEA307,0x1E96F1B1,0x05F50EE6,0xE4685E28,0x43A107E2), + W256(0x1D28D94C,0x0597CD66,0x9EC745F2,0xDC3B2D1E,0xE546E123,0xF8257AA6,0x117C9A30,0x02D21113) + }, + { /* P{238} */ + W256(0x8F37293A,0x84808259,0xDB95552B,0x0B0A87FA,0x2E59A403,0x73963F88,0x8EBD7260,0x36D75CDD), + W256(0xC258F5D4,0x4D242941,0x4015ED2C,0x8DD203E7,0x949C2C89,0x008C9429,0x38ED2A3C,0x0052B3E3), + W256(0xABFE286E,0x7AAAF491,0xA4EC546A,0x97D15582,0x1E9810EF,0x5D4EB295,0xE8784F3C,0x46F21171) + }, + { /* P{239} */ + W256(0xF130CD06,0xD6E2272E,0xA5FCA011,0xBE6B24D6,0x0CC83C25,0xB243EB1F,0x0BC8FC42,0x3B664099), + W256(0x900FB0C1,0xC009F143,0x54ECFBAF,0xB3BDEEC4,0xDB64D788,0x22EE7D00,0x33CE3DF1,0x026B0962), + W256(0x202DCCF2,0x12F86676,0xB996E643,0x732A8168,0x4C422C52,0xF54FF9DC,0xB75C7A10,0x26B11500) + }, + { /* P{240} */ + W256(0xF191A8DC,0x26788EFA,0xE7263590,0xE8DFCCFC,0xAA2026D1,0x157C9362,0x4A5D144F,0x4E32CAAD), + W256(0x563ADB50,0xEC9B891D,0x1F671DCE,0x8D78B1DB,0x282D197C,0x69617115,0x5573A978,0x1AE2643A), + W256(0x4FCF2434,0x09636FB7,0xAF995A40,0xDD881E20,0x5F91C2B7,0xCE211A89,0xFD4900AA,0x6A50999C) + }, + { /* P{241} */ + W256(0x916D6651,0xA901A64E,0xC8CF8F39,0xB968B5A2,0xB8AA4E43,0x5D33A4A9,0x6E1E792D,0x2F5EA746), + W256(0xE8D4A1B7,0x89A32E63,0x4D6CF0C6,0x81F8E9DB,0x4039B74A,0x216CC7B7,0x9ABF60C3,0x3B19C562), + W256(0x8737934E,0xE81E1449,0x65C399F4,0x6B3499B6,0xB51E6884,0xD7978199,0xB4895825,0x105BC430) + }, + { /* P{242} */ + W256(0xF621F64F,0xE96B4AA0,0xE5323071,0xE10D4EFF,0x14199139,0xCFBCC47D,0xE03E31C0,0x05F714E8), + W256(0x12A2CA2B,0xE990577A,0x81C27939,0xC6BFA1A7,0xAD3F21B2,0x9BFF68DC,0x40615194,0x2ED19571), + W256(0x7FEB4A3D,0xB0F981E7,0x137C3028,0xDD112BD4,0x88DA7346,0xF8F3EBC5,0x676E052A,0x380C6FBB) + }, + { /* P{243} */ + W256(0x3F0D7841,0xE23740A6,0xD710A7FC,0x4F44E3A0,0x5C773E57,0xB0E2CDB5,0x242057A1,0x2767944E), + W256(0xDCCF6FA1,0x1788CBB3,0x5CA89DAA,0x60664ABE,0xB2D8D3F5,0xF2615418,0x9A87A9AA,0x2CB8CC24), + W256(0x49A9A2E4,0x76F79F1B,0x0D3E6934,0x7761490D,0xE338299E,0x94ECA394,0x423FA351,0x4C66D193) + }, + { /* P{244} */ + W256(0x7B167FB3,0x29860741,0xA96F4D50,0xD8EE7462,0x05FA8A5C,0x915860D0,0x6ABFE43E,0x7A2DBAB4), + W256(0x15756360,0x055E4148,0xF13335E8,0xB92D55DE,0x0E7A7E61,0xDF4F2F24,0x40D9CB0D,0x6EC868CA), + W256(0x99CB6197,0xAFE1D51D,0x08D20839,0x6CD0BE13,0x57381600,0xE193E85D,0xE7BF8571,0x4A122E9B) + }, + { /* P{245} */ + W256(0xE945B433,0xF5ACB918,0x79FC5FE1,0x1AE37FFA,0xED7BA805,0x911BC333,0xFAE89E01,0x6B8F213A), + W256(0xE3F61F56,0xA5AB485B,0xC5BCC9AF,0x6BD0E91A,0xE1F420CB,0xB149A0BC,0x047FC073,0x29486D5D), + W256(0xD4D2F3C5,0xB2D4DA5A,0xE50034AB,0xD0E3F287,0x85EF0211,0x1AEC0BB1,0xFCE4DE1E,0x7A17675C) + }, + { /* P{246} */ + W256(0x706F8116,0xB96B2855,0x7CCC4854,0x1382F1D6,0x92A438EB,0x532583AD,0x17757420,0x71662521), + W256(0xB79C5ECE,0xF0D8FB4F,0x7A504844,0x85ED103E,0xE20450C9,0xF0D85B2F,0xD72F1427,0x44B642CF), + W256(0xE06C0AE0,0xA55DAE4D,0x931CDD9E,0xD7D3EF74,0x7EB1EB19,0x8BB2E9E8,0x02376355,0x1F237963) + }, + { /* P{247} */ + W256(0x2E03C97E,0x4F29137A,0x3BC118F1,0x6F7520CC,0x007645D9,0x3C3678A9,0x759754EF,0x3F939E7F), + W256(0xF3408157,0x0B4A4B89,0x98BB6E01,0xD91B244D,0x92F96920,0x3C9CF5CD,0xFF26E2B2,0x055C9EB8), + W256(0x321FC3BF,0x555539A7,0x85BE27F6,0xA30E2C05,0xB912F285,0xE7CFAE16,0x88C26918,0x5CC126CC) + }, + { /* P{248} */ + W256(0x90D994DB,0x0E8307EB,0x6E890359,0xE7BB920A,0x35E90551,0x16AF416A,0x13531C29,0x3A28C2AE), + W256(0xE1054BC8,0x677BCEF0,0xC1A3CC47,0xE84D0129,0x736EFA12,0x7B1C8DD2,0x553FA1B2,0x4C9F0B71), + W256(0x302A6AF3,0xF928DA27,0x765EED6E,0x45821985,0x9F16381F,0x1DA41C9A,0x5A8B665E,0x7F757149) + }, + { /* P{249} */ + W256(0x6ECEA774,0x338C379B,0x00E29B08,0xD70DADD8,0x424479CE,0x63F15548,0x1250212A,0x79116D86), + W256(0x01D4A737,0x4BD56A4F,0x40AA9569,0xD5F275E7,0x03E1A57A,0x5164AEFE,0x243BD46B,0x6A7834C3), + W256(0x5BBA7838,0xB11B32F2,0xD630DDC6,0x8E04C3BE,0x6FCC10B6,0xA8FFF171,0x8B186B7D,0x17002BD0) + }, + { /* P{250} */ + W256(0x4EC4BE53,0xA3AB2298,0x2CA3CE50,0x6576E77E,0xE33F81FF,0x741BE0F6,0xA2B99EC0,0x222CAC2C), + W256(0xD9D254D9,0x1BF02D8C,0x0FD963DF,0x060693FC,0xDFCF5D5F,0x6E475F0F,0xA566B430,0x3A4CCEC9), + W256(0x28233251,0x5972D894,0x8BE4A49E,0xEAC18119,0x0D68BF4C,0x22A09297,0xFEAA3B93,0x0D6013F7) + }, + { /* P{251} */ + W256(0xEB928119,0x2CD6A70C,0x45BF3F92,0x2692EDE4,0x90BF49DA,0x8C5CACA7,0xE24118D8,0x7E4D74B6), + W256(0x809DCC58,0xA18731C1,0x4030EF96,0x11434D05,0x9FCBD010,0xE68DA982,0xCC0C179A,0x636EE3FA), + W256(0xC3E9BB85,0xCD9CE414,0xB637120A,0xC10E619E,0x9A75EE40,0x75BE1521,0x2735AFEF,0x30508BFA) + }, + { /* P{252} */ + W256(0x16BB0D37,0x4D530053,0x03CC5483,0xBAC24D52,0x5DC0CB4E,0x1F28E20C,0x8D0672E0,0x1630777E), + W256(0x66E30DF1,0x95F51413,0x9A0FDC58,0x5F411EC0,0x563EA93A,0x20F50861,0xAF225922,0x43003BE0), + W256(0xBB5A5DD1,0xF2273B68,0x2811BBE7,0xDAF11C93,0xF51B2B74,0x953A0A86,0xC7580CC5,0x09FF24C1) + }, + { /* P{253} */ + W256(0x4F3BB0BA,0x82DC02B1,0xC31E249E,0xD9941C8F,0x632D7957,0x2C7A4850,0x7599B474,0x35228A4F), + W256(0x47EC2A0E,0x3E20BAB8,0x8D305391,0x40022AC3,0xC65117FA,0x2A093A82,0x3FAFA224,0x4978381C), + W256(0xF6B009C7,0x59AC5693,0xB989B083,0x38EBC33E,0xBFA62030,0xBFAF9A7C,0x3BF74AB3,0x2E233E3A) + }, + { /* P{254} */ + W256(0x1F661A2F,0x667D59D9,0xE0B13ADD,0x90C091B0,0xB9CFEECD,0x4509A47F,0xEBDC5481,0x390E4209), + W256(0x60DBDD3D,0xC6720314,0xC22C8799,0xFD6BC073,0x94F8C734,0x46FD56CB,0xEE0F1343,0x79AB3492), + W256(0xB8C2A508,0x0B2B4597,0xBA5A1C4F,0x71F8FBE0,0x349EE41B,0x403B3743,0x6D7DB9DF,0x05041B7A) + }, + { /* P{255} */ + W256(0x94BB6B90,0x9E2B2EFB,0x4A6A3FE1,0xF5D4C66E,0xD578B4ED,0x82AF5828,0xA6068797,0x6793D1AF), + W256(0x8AF07244,0x9A55C9C6,0x41DD90A4,0x867F3F98,0xF66845FC,0xD4894F77,0x414914D7,0x2D01687D), + W256(0xD61358BC,0x61F36185,0xDD3DD058,0xE51BD50F,0x6C1A8B59,0x13D47700,0x98B5A8BC,0x16C7949A) + } +}; diff --git a/source/extern/curve25519/source/curve25519_dh.c b/source/extern/curve25519/source/curve25519_dh.c new file mode 100644 index 0000000..600174a --- /dev/null +++ b/source/extern/curve25519/source/curve25519_dh.c @@ -0,0 +1,208 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2015 mehdi sotoodeh + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "../include/external_calls.h" +#include "curve25519_mehdi.h" + +typedef struct +{ + U_WORD X[K_WORDS]; /* x = X/Z */ + U_WORD Z[K_WORDS]; /* */ +} XZ_POINT; + +extern const U_WORD _w_P[K_WORDS]; +extern EDP_BLINDING_CTX edp_custom_blinding; + +/* x coordinate of base point */ +const U8 ecp_BasePoint[32] = { + 9,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0 }; +/* Y = X + X */ +void ecp_MontDouble(XZ_POINT *Y, const XZ_POINT *X) +{ + U_WORD A[K_WORDS], B[K_WORDS]; + /* x2 = (x+z)^2 * (x-z)^2 */ + /* z2 = ((x+z)^2 - (x-z)^2)*((x+z)^2 + ((A-2)/4)((x+z)^2 - (x-z)^2)) */ + ecp_AddReduce(A, X->X, X->Z); /* A = (x+z) */ + ecp_SubReduce(B, X->X, X->Z); /* B = (x-z) */ + ecp_SqrReduce(A, A); /* A = (x+z)^2 */ + ecp_SqrReduce(B, B); /* B = (x-z)^2 */ + ecp_MulReduce(Y->X, A, B); /* x2 = (x+z)^2 * (x-z)^2 */ + ecp_SubReduce(B, A, B); /* B = (x+z)^2 - (x-z)^2 */ + /* (486662-2)/4 = 121665 */ + ecp_WordMulAddReduce(A, A, 121665, B); + ecp_MulReduce(Y->Z, A, B); /* z2 = (B)*((x+z)^2 + ((A-2)/4)(B)) */ +} + +/* return P = P + Q, Q = 2Q */ +void ecp_Mont(XZ_POINT *P, XZ_POINT *Q, IN const U_WORD *Base) +{ + U_WORD A[K_WORDS], B[K_WORDS], C[K_WORDS], D[K_WORDS], E[K_WORDS]; + /* x3 = ((x1-z1)(x2+z2) + (x1+z1)(x2-z2))^2*zb zb=1 */ + /* z3 = ((x1-z1)(x2+z2) - (x1+z1)(x2-z2))^2*xb xb=Base */ + ecp_SubReduce(A, P->X, P->Z); /* A = x1-z1 */ + ecp_AddReduce(B, P->X, P->Z); /* B = x1+z1 */ + ecp_SubReduce(C, Q->X, Q->Z); /* C = x2-z2 */ + ecp_AddReduce(D, Q->X, Q->Z); /* D = x2+z2 */ + ecp_MulReduce(A, A, D); /* A = (x1-z1)(x2+z2) */ + ecp_MulReduce(B, B, C); /* B = (x1+z1)(x2-z2) */ + ecp_AddReduce(E, A, B); /* E = (x1-z1)(x2+z2) + (x1+z1)(x2-z2) */ + ecp_SubReduce(B, A, B); /* B = (x1-z1)(x2+z2) - (x1+z1)(x2-z2) */ + ecp_SqrReduce(P->X, E); /* x3 = ((x1-z1)(x2+z2) + (x1+z1)(x2-z2))^2 */ + ecp_SqrReduce(A, B); /* A = ((x1-z1)(x2+z2) - (x1+z1)(x2-z2))^2 */ + ecp_MulReduce(P->Z, A, Base); /* z3 = ((x1-z1)(x2+z2) - (x1+z1)(x2-z2))^2*Base */ + + /* x4 = (x2+z2)^2 * (x2-z2)^2 */ + /* z4 = ((x2+z2)^2 - (x2-z2)^2)*((x2+z2)^2 + 121665((x2+z2)^2 - (x2-z2)^2)) */ + /* C = (x2-z2) */ + /* D = (x2+z2) */ + ecp_SqrReduce(A, D); /* A = (x2+z2)^2 */ + ecp_SqrReduce(B, C); /* B = (x2-z2)^2 */ + ecp_MulReduce(Q->X, A, B); /* x4 = (x2+z2)^2 * (x2-z2)^2 */ + ecp_SubReduce(B, A, B); /* B = (x2+z2)^2 - (x2-z2)^2 */ + ecp_WordMulAddReduce(A, A, 121665, B); + ecp_MulReduce(Q->Z, A, B); /* z4 = B*((x2+z2)^2 + 121665*B) */ +} + +/* Constant-time measure: */ +/* Use different set of parameters for bit=0 or bit=1 with no conditional jump */ +/* */ +#define ECP_MONT(n) j = (k >> n) & 1; ecp_Mont(PP[j], QP[j], X) + +/* -------------------------------------------------------------------------- */ +/* Return point Q = k*P */ +/* K in a little-endian byte array */ +void ecp_PointMultiply( + OUT U8 *PublicKey, + IN const U8 *BasePoint, + IN const U8 *SecretKey, + IN int len) +{ + int i, j, k; + U_WORD X[K_WORDS]; + XZ_POINT P, Q, *PP[2], *QP[2]; + + ecp_BytesToWords(X, BasePoint); + + /* 1: P = (2k+1)G, Q = (2k+2)G */ + /* 0: Q = (2k+1)G, P = (2k)G */ + + /* Find first non-zero bit */ + while (len-- > 0) + { + k = SecretKey[len]; + for (i = 0; i < 8; i++, k <<= 1) + { + /* P = kG, Q = (k+1)G */ + if (k & 0x80) + { + /* We have first non-zero bit + // This is always bit 254 for keys created according to the spec. + // Start with randomized base point + */ + + ecp_Add(P.Z, X, edp_custom_blinding.zr); /* P.Z = random */ + ecp_MulReduce(P.X, X, P.Z); + ecp_MontDouble(&Q, &P); + + PP[1] = &P; PP[0] = &Q; + QP[1] = &Q; QP[0] = &P; + + /* Everything we reference in the below loop are on the stack + // and already touched (cached) + */ + + while (++i < 8) { k <<= 1; ECP_MONT(7); } + while (len > 0) + { + k = SecretKey[--len]; + ECP_MONT(7); + ECP_MONT(6); + ECP_MONT(5); + ECP_MONT(4); + ECP_MONT(3); + ECP_MONT(2); + ECP_MONT(1); + ECP_MONT(0); + } + + ecp_Inverse(Q.Z, P.Z); + ecp_MulMod(X, P.X, Q.Z); + ecp_WordsToBytes(PublicKey, X); + return; + } + } + } + /* K is 0 */ + mem_fill(PublicKey, 0, 32); +} + +/* -- DH key exchange interfaces ----------------------------------------- */ + +/* Return R = a*P where P is curve25519 base point */ +void x25519_BasePointMultiply(OUT U8 *r, IN const U8 *sk) +{ + Ext_POINT S; + U_WORD t[K_WORDS]; + + ecp_BytesToWords(t, sk); + edp_BasePointMult(&S, t, edp_custom_blinding.zr); + + /* Convert ed25519 point to x25519 point */ + + /* u = (1 + y)/(1 - y) = (Z + Y)/(Z - Y) */ + + ecp_AddReduce(S.t, S.z, S.y); + ecp_SubReduce(S.z, S.z, S.y); + ecp_Inverse(S.z, S.z); + ecp_MulMod(S.t, S.t, S.z); + ecp_WordsToBytes(r, S.t); +} + +/* Return public key associated with sk */ +void curve25519_dh_CalculatePublicKey_fast( + unsigned char *pk, /* [32-bytes] OUT: Public key */ + unsigned char *sk) /* [32-bytes] IN/OUT: Your secret key */ +{ + ecp_TrimSecretKey(sk); + /* Use faster method */ + x25519_BasePointMultiply(pk, sk); +} + +/* Return public key associated with sk */ +void curve25519_dh_CalculatePublicKey( + unsigned char *pk, /* [32-bytes] OUT: Public key */ + unsigned char *sk) /* [32-bytes] IN/OUT: Your secret key */ +{ + ecp_TrimSecretKey(sk); + ecp_PointMultiply(pk, ecp_BasePoint, sk, 32); +} + +/* Create a shared secret */ +void curve25519_dh_CreateSharedKey( + unsigned char *shared, /* [32-bytes] OUT: Created shared key */ + const unsigned char *pk, /* [32-bytes] IN: Other side's public key */ + unsigned char *sk) /* [32-bytes] IN/OUT: Your secret key */ +{ + ecp_TrimSecretKey(sk); + ecp_PointMultiply(shared, pk, sk, 32); +} diff --git a/source/extern/curve25519/source/curve25519_mehdi.c b/source/extern/curve25519/source/curve25519_mehdi.c new file mode 100644 index 0000000..0d95d64 --- /dev/null +++ b/source/extern/curve25519/source/curve25519_mehdi.c @@ -0,0 +1,410 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2015 mehdi sotoodeh + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "../include/external_calls.h" +#include "curve25519_mehdi.h" + +/* + The curve used is y2 = x^3 + 486662x^2 + x, a Montgomery curve, over + the prime field defined by the prime number 2^255 - 19, and it uses the + base point x = 9. + Protocol uses compressed elliptic point (only X coordinates), so it + allows for efficient use of the Montgomery ladder for ECDH, using only + XZ coordinates. + + The curve is birationally equivalent to Ed25519 (Twisted Edwards curve). + + b = 256 + p = 2**255 - 19 + l = 2**252 + 27742317777372353535851937790883648493 + + This library is a constant-time implementation of field operations +*/ + +typedef struct +{ + U32 X[8]; /* x = X/Z */ + U32 Z[8]; /* */ +} XZ_POINT; + +const U32 _w_P[8] = { + 0xFFFFFFED,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0x7FFFFFFF +}; + +/* Maximum number of prime p that fits into 256-bits */ +const U32 _w_maxP[8] = { /* 2*P < 2**256 */ + 0xFFFFFFDA,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF, + 0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF +}; + +void ecp_SetValue(U32* X, U32 value) +{ + X[0] = value; + X[1] = X[2] = X[3] = X[4] = X[5] = X[6] = X[7] = 0; +} + +/* Y = X */ +void ecp_Copy(U32* Y, const U32* X) +{ + memcpy(Y, X, 8*sizeof(U32)); +} + +int ecp_CmpNE(const U32* X, const U32* Y) +{ + return ((X[0] ^ Y[0]) | (X[1] ^ Y[1]) | (X[2] ^ Y[2]) | (X[3] ^ Y[3]) | + (X[4] ^ Y[4]) | (X[5] ^ Y[5]) | (X[6] ^ Y[6]) | (X[7] ^ Y[7])); +} + +int ecp_CmpLT(const U32* X, const U32* Y) +{ + U32 T[8]; + return ecp_Sub(T, X, Y); +} + +#define ECP_ADD_C0(Y,X,V) c.u64 = (U64)(X) + (V); Y = c.u32.lo; +#define ECP_ADD_C1(Y,X) c.u64 = (U64)(X) + c.u32.hi; Y = c.u32.lo; + +#define ECP_SUB_C0(Y,X,V) c.s64 = (U64)(X) - (V); Y = c.u32.lo; +#define ECP_SUB_C1(Y,X) c.s64 = (U64)(X) + (S64)c.s32.hi; Y = c.u32.lo; + +#define ECP_MULSET_W0(Y,b,X) c.u64 = (U64)(b)*(X); Y = c.u32.lo; +#define ECP_MULSET_W1(Y,b,X) c.u64 = (U64)(b)*(X) + c.u32.hi; Y = c.u32.lo; + +#define ECP_MULADD_W0(Z,Y,b,X) c.u64 = (U64)(b)*(X) + (Y); Z = c.u32.lo; +#define ECP_MULADD_W1(Z,Y,b,X) c.u64 = (U64)(b)*(X) + (U64)(Y) + c.u32.hi; Z = c.u32.lo; + +#define ECP_ADD32(Z,X,Y) c.u64 = (U64)(X) + (Y); Z = c.u32.lo; +#define ECP_ADC32(Z,X,Y) c.u64 = (U64)(X) + (U64)(Y) + c.u32.hi; Z = c.u32.lo; +#define ECP_SUB32(Z,X,Y) b.s64 = (S64)(X) - (Y); Z = b.s32.lo; +#define ECP_SBC32(Z,X,Y) b.s64 = (S64)(X) - (U64)(Y) + b.s32.hi; Z = b.s32.lo; + +/* Computes Z = X+Y */ +U32 ecp_Add(U32* Z, const U32* X, const U32* Y) +{ + M64 c; + + ECP_ADD32(Z[0], X[0], Y[0]); + ECP_ADC32(Z[1], X[1], Y[1]); + ECP_ADC32(Z[2], X[2], Y[2]); + ECP_ADC32(Z[3], X[3], Y[3]); + ECP_ADC32(Z[4], X[4], Y[4]); + ECP_ADC32(Z[5], X[5], Y[5]); + ECP_ADC32(Z[6], X[6], Y[6]); + ECP_ADC32(Z[7], X[7], Y[7]); + return c.u32.hi; +} + +/* Computes Z = X-Y */ +S32 ecp_Sub(U32* Z, const U32* X, const U32* Y) +{ + M64 b; + ECP_SUB32(Z[0], X[0], Y[0]); + ECP_SBC32(Z[1], X[1], Y[1]); + ECP_SBC32(Z[2], X[2], Y[2]); + ECP_SBC32(Z[3], X[3], Y[3]); + ECP_SBC32(Z[4], X[4], Y[4]); + ECP_SBC32(Z[5], X[5], Y[5]); + ECP_SBC32(Z[6], X[6], Y[6]); + ECP_SBC32(Z[7], X[7], Y[7]); + return b.s32.hi; +} + +/* Computes Z = X+Y mod P */ +void ecp_AddReduce(U32* Z, const U32* X, const U32* Y) +{ + M64 c; + c.u32.hi = ecp_Add(Z, X, Y) * 38; + + /* Z += c.u32.hi * 38 */ + ECP_ADD_C0(Z[0], Z[0], c.u32.hi); + ECP_ADD_C1(Z[1], Z[1]); + ECP_ADD_C1(Z[2], Z[2]); + ECP_ADD_C1(Z[3], Z[3]); + ECP_ADD_C1(Z[4], Z[4]); + ECP_ADD_C1(Z[5], Z[5]); + ECP_ADD_C1(Z[6], Z[6]); + ECP_ADD_C1(Z[7], Z[7]); + + /* One more carry at most */ + ECP_ADD_C0(Z[0], Z[0], c.u32.hi*38); + ECP_ADD_C1(Z[1], Z[1]); + ECP_ADD_C1(Z[2], Z[2]); + ECP_ADD_C1(Z[3], Z[3]); + ECP_ADD_C1(Z[4], Z[4]); + ECP_ADD_C1(Z[5], Z[5]); + ECP_ADD_C1(Z[6], Z[6]); + ECP_ADD_C1(Z[7], Z[7]); +} + +/* Computes Z = X-Y mod P */ +void ecp_SubReduce(U32* Z, const U32* X, const U32* Y) +{ + M64 c; + c.u32.hi = ecp_Sub(Z, X, Y) & 38; + + ECP_SUB_C0(Z[0], Z[0], c.u32.hi); + ECP_SUB_C1(Z[1], Z[1]); + ECP_SUB_C1(Z[2], Z[2]); + ECP_SUB_C1(Z[3], Z[3]); + ECP_SUB_C1(Z[4], Z[4]); + ECP_SUB_C1(Z[5], Z[5]); + ECP_SUB_C1(Z[6], Z[6]); + ECP_SUB_C1(Z[7], Z[7]); + + ECP_SUB_C0(Z[0], Z[0], c.u32.hi & 38); + ECP_SUB_C1(Z[1], Z[1]); + ECP_SUB_C1(Z[2], Z[2]); + ECP_SUB_C1(Z[3], Z[3]); + ECP_SUB_C1(Z[4], Z[4]); + ECP_SUB_C1(Z[5], Z[5]); + ECP_SUB_C1(Z[6], Z[6]); + ECP_SUB_C1(Z[7], Z[7]); +} + +void ecp_Mod(U32 *X) +{ + U32 T[8]; + U32 c = (U32)ecp_Sub(X, X, _w_P); + + /* set T = 0 if c=0, else T = P */ + + T[0] = c & 0xFFFFFFED; + T[1] = T[2] = T[3] = T[4] = T[5] = T[6] = c; + T[7] = c >> 1; + + ecp_Add(X, X, T); /* X += 0 or P */ + + /* In case there is another P there */ + + c = (U32)ecp_Sub(X, X, _w_P); + + /* set T = 0 if c=0, else T = P */ + + T[0] = c & 0xFFFFFFED; + T[1] = T[2] = T[3] = T[4] = T[5] = T[6] = c; + T[7] = c >> 1; + + ecp_Add(X, X, T); /* X += 0 or P */ +} + +/* Computes Y = b*X */ +static void ecp_mul_set(U32* Y, U32 b, const U32* X) +{ + M64 c; + ECP_MULSET_W0(Y[0], b, X[0]); + ECP_MULSET_W1(Y[1], b, X[1]); + ECP_MULSET_W1(Y[2], b, X[2]); + ECP_MULSET_W1(Y[3], b, X[3]); + ECP_MULSET_W1(Y[4], b, X[4]); + ECP_MULSET_W1(Y[5], b, X[5]); + ECP_MULSET_W1(Y[6], b, X[6]); + ECP_MULSET_W1(Y[7], b, X[7]); + Y[8] = c.u32.hi; +} + +/* Computes Y += b*X */ +/* Addition is performed on lower 8-words of Y */ +static void ecp_mul_add(U32* Y, U32 b, const U32* X) +{ + M64 c; + ECP_MULADD_W0(Y[0], Y[0], b, X[0]); + ECP_MULADD_W1(Y[1], Y[1], b, X[1]); + ECP_MULADD_W1(Y[2], Y[2], b, X[2]); + ECP_MULADD_W1(Y[3], Y[3], b, X[3]); + ECP_MULADD_W1(Y[4], Y[4], b, X[4]); + ECP_MULADD_W1(Y[5], Y[5], b, X[5]); + ECP_MULADD_W1(Y[6], Y[6], b, X[6]); + ECP_MULADD_W1(Y[7], Y[7], b, X[7]); + Y[8] = c.u32.hi; +} + +/* Computes Z = Y + b*X and return carry */ +void ecp_WordMulAddReduce(U32 *Z, const U32* Y, U32 b, const U32* X) +{ + M64 c; + ECP_MULADD_W0(Z[0], Y[0], b, X[0]); + ECP_MULADD_W1(Z[1], Y[1], b, X[1]); + ECP_MULADD_W1(Z[2], Y[2], b, X[2]); + ECP_MULADD_W1(Z[3], Y[3], b, X[3]); + ECP_MULADD_W1(Z[4], Y[4], b, X[4]); + ECP_MULADD_W1(Z[5], Y[5], b, X[5]); + ECP_MULADD_W1(Z[6], Y[6], b, X[6]); + ECP_MULADD_W1(Z[7], Y[7], b, X[7]); + + /* Z += c.u32.hi * 38 */ + ECP_MULADD_W0(Z[0], Z[0], c.u32.hi, 38); + ECP_ADD_C1(Z[1], Z[1]); + ECP_ADD_C1(Z[2], Z[2]); + ECP_ADD_C1(Z[3], Z[3]); + ECP_ADD_C1(Z[4], Z[4]); + ECP_ADD_C1(Z[5], Z[5]); + ECP_ADD_C1(Z[6], Z[6]); + ECP_ADD_C1(Z[7], Z[7]); + + /* One more time at most */ + ECP_MULADD_W0(Z[0], Z[0], c.u32.hi, 38); + ECP_ADD_C1(Z[1], Z[1]); + ECP_ADD_C1(Z[2], Z[2]); + ECP_ADD_C1(Z[3], Z[3]); + ECP_ADD_C1(Z[4], Z[4]); + ECP_ADD_C1(Z[5], Z[5]); + ECP_ADD_C1(Z[6], Z[6]); + ECP_ADD_C1(Z[7], Z[7]); +} + +/* Computes Z = X*Y mod P. */ +/* Output fits into 8 words but could be greater than P */ +void ecp_MulReduce(U32* Z, const U32* X, const U32* Y) +{ + U32 T[16]; + + ecp_mul_set(T+0, X[0], Y); + ecp_mul_add(T+1, X[1], Y); + ecp_mul_add(T+2, X[2], Y); + ecp_mul_add(T+3, X[3], Y); + ecp_mul_add(T+4, X[4], Y); + ecp_mul_add(T+5, X[5], Y); + ecp_mul_add(T+6, X[6], Y); + ecp_mul_add(T+7, X[7], Y); + + /* We have T = X*Y, now do the reduction in size */ + + ecp_WordMulAddReduce(Z, T, 38, T+8); +} + +/* Computes Z = X*Y */ +void ecp_Mul(U32* Z, const U32* X, const U32* Y) +{ + ecp_mul_set(Z+0, X[0], Y); + ecp_mul_add(Z+1, X[1], Y); + ecp_mul_add(Z+2, X[2], Y); + ecp_mul_add(Z+3, X[3], Y); + ecp_mul_add(Z+4, X[4], Y); + ecp_mul_add(Z+5, X[5], Y); + ecp_mul_add(Z+6, X[6], Y); + ecp_mul_add(Z+7, X[7], Y); +} + +/* Computes Z = X*Y mod P. */ +void ecp_SqrReduce(U32* Y, const U32* X) +{ + /* TBD: Implementation is based on multiply */ + /* Optimize for squaring */ + + U32 T[16]; + + ecp_mul_set(T+0, X[0], X); + ecp_mul_add(T+1, X[1], X); + ecp_mul_add(T+2, X[2], X); + ecp_mul_add(T+3, X[3], X); + ecp_mul_add(T+4, X[4], X); + ecp_mul_add(T+5, X[5], X); + ecp_mul_add(T+6, X[6], X); + ecp_mul_add(T+7, X[7], X); + + /* We have T = X*X, now do the reduction in size */ + + ecp_WordMulAddReduce(Y, T, 38, T+8); +} + +/* Computes Z = X*Y mod P. */ +void ecp_MulMod(U32* Z, const U32* X, const U32* Y) +{ + ecp_MulReduce(Z, X, Y); + ecp_Mod(Z); +} + +/* Courtesy of DJB */ +/* Return out = 1/z mod P */ +void ecp_Inverse(U32 *out, const U32 *z) +{ + int i; + U32 t0[8],t1[8],z2[8],z9[8],z11[8]; + U32 z2_5_0[8],z2_10_0[8],z2_20_0[8],z2_50_0[8],z2_100_0[8]; + + /* 2 */ ecp_SqrReduce(z2,z); + /* 4 */ ecp_SqrReduce(t1,z2); + /* 8 */ ecp_SqrReduce(t0,t1); + /* 9 */ ecp_MulReduce(z9,t0,z); + /* 11 */ ecp_MulReduce(z11,z9,z2); + /* 22 */ ecp_SqrReduce(t0,z11); + /* 2^5 - 2^0 = 31 */ ecp_MulReduce(z2_5_0,t0,z9); + + /* 2^6 - 2^1 */ ecp_SqrReduce(t0,z2_5_0); + /* 2^7 - 2^2 */ ecp_SqrReduce(t1,t0); + /* 2^8 - 2^3 */ ecp_SqrReduce(t0,t1); + /* 2^9 - 2^4 */ ecp_SqrReduce(t1,t0); + /* 2^10 - 2^5 */ ecp_SqrReduce(t0,t1); + /* 2^10 - 2^0 */ ecp_MulReduce(z2_10_0,t0,z2_5_0); + + /* 2^11 - 2^1 */ ecp_SqrReduce(t0,z2_10_0); + /* 2^12 - 2^2 */ ecp_SqrReduce(t1,t0); + /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { + ecp_SqrReduce(t0,t1); + ecp_SqrReduce(t1,t0); } + /* 2^20 - 2^0 */ ecp_MulReduce(z2_20_0,t1,z2_10_0); + + /* 2^21 - 2^1 */ ecp_SqrReduce(t0,z2_20_0); + /* 2^22 - 2^2 */ ecp_SqrReduce(t1,t0); + /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { + ecp_SqrReduce(t0,t1); + ecp_SqrReduce(t1,t0); } + /* 2^40 - 2^0 */ ecp_MulReduce(t0,t1,z2_20_0); + + /* 2^41 - 2^1 */ ecp_SqrReduce(t1,t0); + /* 2^42 - 2^2 */ ecp_SqrReduce(t0,t1); + /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { + ecp_SqrReduce(t1,t0); + ecp_SqrReduce(t0,t1); } + /* 2^50 - 2^0 */ ecp_MulReduce(z2_50_0,t0,z2_10_0); + + /* 2^51 - 2^1 */ ecp_SqrReduce(t0,z2_50_0); + /* 2^52 - 2^2 */ ecp_SqrReduce(t1,t0); + /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { + ecp_SqrReduce(t0,t1); + ecp_SqrReduce(t1,t0); } + /* 2^100 - 2^0 */ ecp_MulReduce(z2_100_0,t1,z2_50_0); + + /* 2^101 - 2^1 */ ecp_SqrReduce(t1,z2_100_0); + /* 2^102 - 2^2 */ ecp_SqrReduce(t0,t1); + /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { + ecp_SqrReduce(t1,t0); + ecp_SqrReduce(t0,t1); } + /* 2^200 - 2^0 */ ecp_MulReduce(t1,t0,z2_100_0); + + /* 2^201 - 2^1 */ ecp_SqrReduce(t0,t1); + /* 2^202 - 2^2 */ ecp_SqrReduce(t1,t0); + /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { + ecp_SqrReduce(t0,t1); + ecp_SqrReduce(t1,t0); } + /* 2^250 - 2^0 */ ecp_MulReduce(t0,t1,z2_50_0); + + /* 2^251 - 2^1 */ ecp_SqrReduce(t1,t0); + /* 2^252 - 2^2 */ ecp_SqrReduce(t0,t1); + /* 2^253 - 2^3 */ ecp_SqrReduce(t1,t0); + /* 2^254 - 2^4 */ ecp_SqrReduce(t0,t1); + /* 2^255 - 2^5 */ ecp_SqrReduce(t1,t0); + /* 2^255 - 21 */ ecp_MulReduce(out,t1,z11); +} + diff --git a/source/extern/curve25519/source/curve25519_mehdi.h b/source/extern/curve25519/source/curve25519_mehdi.h new file mode 100644 index 0000000..bb251e5 --- /dev/null +++ b/source/extern/curve25519/source/curve25519_mehdi.h @@ -0,0 +1,175 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2015 mehdi sotoodeh + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __curve25519_mehdi_h__ +#define __curve25519_mehdi_h__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "BaseTypes.h" + +#define ECP_VERSION_STR "1.2.0" + +#ifdef USE_ASM_LIB +#define U_WORD U64 +#define S_WORD S64 +#define WORDSIZE_64 +#define W64(lo,hi) ((U64)hi<<32)+lo +#else +#define U_WORD U32 +#define S_WORD S32 +#define WORDSIZE_32 +#define W64(lo,hi) lo,hi +#endif + +#define K_BYTES 32 +#define K_WORDS (K_BYTES/sizeof(U_WORD)) + +#define W256(x0,x1,x2,x3,x4,x5,x6,x7) {W64(x0,x1),W64(x2,x3),W64(x4,x5),W64(x6,x7)} + +/* Affine coordinates */ +typedef struct { + U_WORD x[K_WORDS]; + U_WORD y[K_WORDS]; +} Affine_POINT; + +/* Projective coordinates */ +typedef struct { + U_WORD x[K_WORDS]; /* x/z */ + U_WORD y[K_WORDS]; /* y/z */ + U_WORD z[K_WORDS]; + U_WORD t[K_WORDS]; /* xy/z */ +} Ext_POINT; + +/* pre-computed, extended point */ +typedef struct +{ + U_WORD YpX[K_WORDS]; /* Y+X */ + U_WORD YmX[K_WORDS]; /* Y-X */ + U_WORD T2d[K_WORDS]; /* 2d*T */ + U_WORD Z2[K_WORDS]; /* 2*Z */ +} PE_POINT; + +/* pre-computed, Affine point */ +typedef struct +{ + U_WORD YpX[K_WORDS]; /* Y+X */ + U_WORD YmX[K_WORDS]; /* Y-X */ + U_WORD T2d[K_WORDS]; /* 2d*T */ +} PA_POINT; + +typedef struct { + U_WORD bl[K_WORDS]; + U_WORD zr[K_WORDS]; + PE_POINT BP; +} EDP_BLINDING_CTX; + +extern const U8 ecp_BasePoint[K_BYTES]; + +/* Return point Q = k*P */ +void ecp_PointMultiply(OUT U8 *Q, IN const U8 *P, IN const U8 *K, IN int len); + +/* Set low and high bits */ +void ecp_TrimSecretKey(U8 *X); + +/* -- utils ----------------------------------------------------------------- */ + +/* Convert big-endian byte array to little-endian byte array and vice versa */ +U8* ecp_ReverseByteOrder(OUT U8 *Y, IN const U8 *X); +/* Convert little-endian byte array to little-endian word array */ +U_WORD* ecp_BytesToWords(OUT U_WORD *Y, IN const U8 *X); +/* Convert little-endian word array to little-endian byte array */ +U8* ecp_WordsToBytes(OUT U8 *Y, IN const U_WORD *X); +U8* ecp_EncodeInt(OUT U8 *Y, IN const U_WORD *X, IN U8 parity); +U8 ecp_DecodeInt(OUT U_WORD *Y, IN const U8 *X); + +/* -- base point order ------------------------------------------------------ */ + +/* Z = (X*Y)/R mod BPO */ +void eco_MontMul(OUT U_WORD *Z, IN const U_WORD *X, IN const U_WORD *Y); +/* Return Y = X*R mod BPO */ +void eco_ToMont(OUT U_WORD *Y, IN const U_WORD *X); +/* Return Y = X/R mod BPO */ +void eco_FromMont(OUT U_WORD *Y, IN const U_WORD *X); +/* Calculate Y = X**E mod BPO */ +void eco_ExpModBPO(OUT U_WORD *Y, IN const U_WORD *X, IN const U8 *E, IN int bytes); +/* Calculate Y = 1/X mod BPO */ +void eco_InvModBPO(OUT U_WORD *Y, IN const U_WORD *X); +/* Z = X*Y mod BPO */ +void eco_MulReduce(OUT U_WORD *Z, IN const U_WORD *X, IN const U_WORD *Y); +/* Return Y = D mod BPO where D is 512-bit big-endian byte array (i.e SHA512 digest) */ +void eco_DigestToWords( OUT U_WORD *Y, IN const U8 *D); +/* Z = X + Y mod BPO */ +void eco_AddReduce(OUT U_WORD *Z, IN const U_WORD *X, IN const U_WORD *Y); +/* X mod BPO */ +void eco_Mod(U_WORD *X); + +#define ed25519_PackPoint(buff, Y, parity) ecp_EncodeInt(buff, Y, (U8)(parity & 1)) + +/* -- big-number ------------------------------------------------------------ */ +U_WORD ecp_Add(U_WORD* Z, const U_WORD* X, const U_WORD* Y); +S_WORD ecp_Sub(U_WORD* Z, const U_WORD* X, const U_WORD* Y); +void ecp_SetValue(U_WORD* X, U_WORD value); +void ecp_Copy(U_WORD* Y, const U_WORD* X); +void ecp_AddReduce(U_WORD* Z, const U_WORD* X, const U_WORD* Y); +void ecp_SubReduce(U_WORD* Z, const U_WORD* X, const U_WORD* Y); +void ecp_MulReduce(U_WORD* Z, const U_WORD* X, const U_WORD* Y); +void ecp_SqrReduce(U_WORD* Y, const U_WORD* X); +void ecp_ModExp2523(U_WORD *Y, const U_WORD *X); +void ecp_Inverse(U_WORD *out, const U_WORD *z); +void ecp_MulMod(U_WORD* Z, const U_WORD* X, const U_WORD* Y); +void ecp_Mul(U_WORD* Z, const U_WORD* X, const U_WORD* Y); +/* Computes Y = b*X */ +void ecp_WordMulSet(U_WORD *Y, U_WORD b, const U_WORD* X); +/* Computes Z = Y + b*X and return carry */ +U_WORD ecp_WordMulAdd(U_WORD *Z, const U_WORD* Y, U_WORD b, const U_WORD* X); +/* Computes Z = Y + b*X */ +void ecp_WordMulAddReduce(U_WORD *Z, const U_WORD* Y, U_WORD b, const U_WORD* X); +void ecp_Mod(U_WORD* X); +int ecp_CmpNE(const U_WORD* X, const U_WORD* Y); +int ecp_CmpLT(const U_WORD* X, const U_WORD* Y); +/* Calculate: Y = [b:X] mod BPO */ +void eco_ReduceHiWord(U_WORD* Y, U_WORD b, const U_WORD* X); + +/* -- ed25519 --------------------------------------------------------------- */ +void ed25519_UnpackPoint(Affine_POINT *r, const unsigned char *p); +void ed25519_CalculateX(OUT U_WORD *X, IN const U_WORD *Y, U_WORD parity); +void edp_AddAffinePoint(Ext_POINT *p, const PA_POINT *q); +void edp_AddBasePoint(Ext_POINT *p); +void edp_AddPoint(Ext_POINT *r, const Ext_POINT *p, const PE_POINT *q); +void edp_DoublePoint(Ext_POINT *p); +void edp_ComputePermTable(PE_POINT *qtable, Ext_POINT *Q); +void edp_ExtPoint2PE(PE_POINT *r, const Ext_POINT *p); +void edp_BasePointMult(OUT Ext_POINT *S, IN const U_WORD *sk, IN const U_WORD *R); +void edp_BasePointMultiply(OUT Affine_POINT *Q, IN const U_WORD *sk, + IN const void *blinding); +void ecp_4Folds(U8* Y, const U_WORD* X); +void ecp_8Folds(U8* Y, const U_WORD* X); + +#ifdef __cplusplus +} +#endif +#endif /* __curve25519_mehdi_h__ */ \ No newline at end of file diff --git a/source/extern/curve25519/source/curve25519_order.c b/source/extern/curve25519/source/curve25519_order.c new file mode 100644 index 0000000..3abb3c3 --- /dev/null +++ b/source/extern/curve25519/source/curve25519_order.c @@ -0,0 +1,155 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2015 mehdi sotoodeh + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "curve25519_mehdi.h" + +/* + This library provides support for mod BPO (Base Point Order) operations + + BPO = 2**252 + 27742317777372353535851937790883648493 + BPO = 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED + + If you keep adding points together, the result repeats every BPO times. + Based on this, you may use: + + public_key = (private_key mod BPO)*BasePoint + Split key example: + k1 = random() + k2 = 1/k1 mod BPO --> k1*k2 = 1 mod BPO + P1 = k1*P0 --> P2 = k2*P1 = k2*k1*P0 = P0 + See selftest code for some examples of BPO usage + + This library is used for implementation of EdDSA sign/verify. +*/ + +const U_WORD _w_NxBPO[16][K_WORDS] = { /* n*BPO */ + W256(0,0,0,0,0,0,0,0), + W256(0x5CF5D3ED,0x5812631A,0xA2F79CD6,0x14DEF9DE,0,0,0,0x10000000), + W256(0xB9EBA7DA,0xB024C634,0x45EF39AC,0x29BDF3BD,0,0,0,0x20000000), + W256(0x16E17BC7,0x0837294F,0xE8E6D683,0x3E9CED9B,0,0,0,0x30000000), + W256(0x73D74FB4,0x60498C69,0x8BDE7359,0x537BE77A,0,0,0,0x40000000), + W256(0xD0CD23A1,0xB85BEF83,0x2ED6102F,0x685AE159,0,0,0,0x50000000), + W256(0x2DC2F78E,0x106E529E,0xD1CDAD06,0x7D39DB37,0,0,0,0x60000000), + W256(0x8AB8CB7B,0x6880B5B8,0x74C549DC,0x9218D516,0,0,0,0x70000000), + W256(0xE7AE9F68,0xC09318D2,0x17BCE6B2,0xA6F7CEF5,0,0,0,0x80000000), + W256(0x44A47355,0x18A57BED,0xBAB48389,0xBBD6C8D3,0,0,0,0x90000000), + W256(0xA19A4742,0x70B7DF07,0x5DAC205F,0xD0B5C2B2,0,0,0,0xA0000000), + W256(0xFE901B2F,0xC8CA4221,0x00A3BD35,0xE594BC91,0,0,0,0xB0000000), + W256(0x5B85EF1C,0x20DCA53C,0xA39B5A0C,0xFA73B66F,0,0,0,0xC0000000), + W256(0xB87BC309,0x78EF0856,0x4692F6E2,0x0F52B04E,1,0,0,0xD0000000), + W256(0x157196F6,0xD1016B71,0xE98A93B8,0x2431AA2C,1,0,0,0xE0000000), + W256(0x72676AE3,0x2913CE8B,0x8C82308F,0x3910A40B,1,0,0,0xF0000000) +}; + +#define minusR_0 0xCF5D3ED0 +#define minusR_1 0x812631A5 +#define minusR_2 0x2F79CD65 +#define minusR_3 0x4DEF9DEA +#define minusR_4 1 +#define minusR_5 0 +#define minusR_6 0 +#define minusR_7 0 + +/* Calculate: Y = [b:X] mod BPO +// For R = 2^256, we calculate Y = b*R + X mod BPO +// Since -R mod BPO is only 129-bits, it reduces number of multiplications if +// we calculate: Y = X - b*(-R) mod BPO instead +// Note that b*(-R) is 161-bits at most and does not need reduction. +*/ +void eco_ReduceHiWord(U32* Y, U32 b, const U32* X) +{ + M64 c; + U32 T[8]; + + /* Set T = b*(-R) */ + + c.u64 = (U64)b*minusR_0; + T[0] = c.u32.lo; + c.u64 = (U64)b*minusR_1 + c.u32.hi; + T[1] = c.u32.lo; + c.u64 = (U64)b*minusR_2 + c.u32.hi; + T[2] = c.u32.lo; + c.u64 = (U64)b*minusR_3 + c.u32.hi; + T[3] = c.u32.lo; + c.u64 = (U64)b + c.u32.hi; + T[4] = c.u32.lo; + T[5] = c.u32.hi; + T[6] = 0; + T[7] = 0; + + /* Y = X - T */ + c.s32.hi = ecp_Sub(Y, X, T); + + /* Add BPO if there is a borrow */ + + ecp_Add(Y, Y, _w_NxBPO[c.s32.hi & 1]); +} + +/* Z = X*Y mod BPO */ +void eco_MulReduce(OUT U32 *Z, IN const U32 *X, IN const U32 *Y) +{ + U32 T[16]; + ecp_Mul(T, X, Y); /* T = X*Y */ + eco_ReduceHiWord(T+7, T[15], T+7); + eco_ReduceHiWord(T+6, T[14], T+6); + eco_ReduceHiWord(T+5, T[13], T+5); + eco_ReduceHiWord(T+4, T[12], T+4); + eco_ReduceHiWord(T+3, T[11], T+3); + eco_ReduceHiWord(T+2, T[10], T+2); + eco_ReduceHiWord(T+1, T[9], T+1); + eco_ReduceHiWord(Z, T[8], T+0); +} + +/* X mod BPO */ +void eco_Mod(U32 *X) +{ + S32 c = ecp_Sub(X, X, _w_NxBPO[X[7] >> 28]); + ecp_Add(X, X, _w_NxBPO[c & 1]); +} + +/* Z = X + Y mod BPO */ +void eco_AddReduce(OUT U32 *Z, IN const U32 *X, IN const U32 *Y) +{ + U32 c = ecp_Add(Z, X, Y); + eco_ReduceHiWord(Z, c, Z); +} + +/* Return Y = D mod BPO where D is 512-bit message digest (i.e SHA512 digest) */ +void eco_DigestToWords( OUT U32 *Y, IN const U8 *md) +{ + U32 T[16]; + + /* We use digest value as little-endian byte array. */ + ecp_BytesToWords(T, md); + ecp_BytesToWords(T+8, md+32); + + eco_ReduceHiWord(T+7, T[15], T+7); + eco_ReduceHiWord(T+6, T[14], T+6); + eco_ReduceHiWord(T+5, T[13], T+5); + eco_ReduceHiWord(T+4, T[12], T+4); + eco_ReduceHiWord(T+3, T[11], T+3); + eco_ReduceHiWord(T+2, T[10], T+2); + eco_ReduceHiWord(T+1, T[9], T+1); + eco_ReduceHiWord(Y, T[8], T+0); +} diff --git a/source/extern/curve25519/source/curve25519_utils.c b/source/extern/curve25519/source/curve25519_utils.c new file mode 100644 index 0000000..c6ffe96 --- /dev/null +++ b/source/extern/curve25519/source/curve25519_utils.c @@ -0,0 +1,153 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2015 mehdi sotoodeh + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "curve25519_mehdi.h" + +/* Trim private key */ +void ecp_TrimSecretKey(U8 *X) +{ + X[0] &= 0xf8; + X[31] = (X[31] | 0x40) & 0x7f; +} + +/* Convert big-endian byte array to little-endian byte array and vice versa */ +U8* ecp_ReverseByteOrder(OUT U8 *Y, IN const U8 *X) +{ + int i; + for (i = 0; i < 32; i++) Y[i] = X[31-i]; + return Y; +} + +/* Convert little-endian byte array to little-endian word array */ +U32* ecp_BytesToWords(OUT U32 *Y, IN const U8 *X) +{ + int i; + M32 m; + + for (i = 0; i < 8; i++) + { + m.u8.b0 = *X++; + m.u8.b1 = *X++; + m.u8.b2 = *X++; + m.u8.b3 = *X++; + + Y[i] = m.u32; + } + return Y; +} + +/* Convert little-endian word array to little-endian byte array */ +U8* ecp_WordsToBytes(OUT U8 *Y, IN const U32 *X) +{ + int i; + M32 m; + + for (i = 0; i < 32;) + { + m.u32 = *X++; + Y[i++] = m.u8.b0; + Y[i++] = m.u8.b1; + Y[i++] = m.u8.b2; + Y[i++] = m.u8.b3; + } + return Y; +} + +U8* ecp_EncodeInt(OUT U8 *Y, IN const U32 *X, IN U8 parity) +{ + int i; + M32 m; + + for (i = 0; i < 28;) + { + m.u32 = *X++; + Y[i++] = m.u8.b0; + Y[i++] = m.u8.b1; + Y[i++] = m.u8.b2; + Y[i++] = m.u8.b3; + } + + m.u32 = *X; + Y[28] = m.u8.b0; + Y[29] = m.u8.b1; + Y[30] = m.u8.b2; + Y[31] = (U8)((m.u8.b3 & 0x7f) | (parity << 7)); + + return Y; +} + +U8 ecp_DecodeInt(OUT U32 *Y, IN const U8 *X) +{ + int i; + M32 m; + + for (i = 0; i < 7; i++) + { + m.u8.b0 = *X++; + m.u8.b1 = *X++; + m.u8.b2 = *X++; + m.u8.b3 = *X++; + + Y[i] = m.u32; + } + + m.u8.b0 = *X++; + m.u8.b1 = *X++; + m.u8.b2 = *X++; + m.u8.b3 = *X & 0x7f; + + Y[7] = m.u32; + + return (U8)((*X >> 7) & 1); +} + +void ecp_4Folds(U8* Y, const U32* X) +{ + int i, j; + U8 a, b; + for (i = 32; i-- > 0; Y++) + { + a = 0; + b = 0; + for (j = 8; j > 1;) + { + j -= 2; + a = (a << 1) + ((X[j+1] >> i) & 1); + b = (b << 1) + ((X[j] >> i) & 1); + } + Y[0] = a; + Y[32] = b; + } +} + +void ecp_8Folds(U8* Y, const U32* X) +{ + int i, j; + U8 a = 0; + for (i = 32; i-- > 0;) + { + for (j = 8; j-- > 0;) a = (a << 1) + ((X[j] >> i) & 1); + *Y++ = a; + } +} diff --git a/source/extern/curve25519/source/custom_blind.c b/source/extern/curve25519/source/custom_blind.c new file mode 100644 index 0000000..207109a --- /dev/null +++ b/source/extern/curve25519/source/custom_blind.c @@ -0,0 +1,27 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2015 mehdi sotoodeh + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "curve25519_mehdi.h" +#include "custom_blind.h" + diff --git a/source/extern/curve25519/source/custom_blind.h b/source/extern/curve25519/source/custom_blind.h new file mode 100644 index 0000000..7d06f86 --- /dev/null +++ b/source/extern/curve25519/source/custom_blind.h @@ -0,0 +1,11 @@ +EDP_BLINDING_CTX edp_custom_blinding = +{ + W256(0xDB763B3D,0x2F33DD36,0xF8DC6F74,0x98C50273,0x8216E0D5,0x1AA522E6,0x6BFD2924,0x04BEFBE2), + W256(0x73FF0C54,0x459E8BA8,0x84F9550B,0xDBF5F46A,0x6DB0E537,0x65F44FFD,0x2AED4E78,0x2CF92B82), + { + W256(0xAA6B12E6,0x7E6A2126,0x2E016899,0x80453AE0,0x6F300787,0x7A7E739E,0x264D5BA3,0x4C34AA79), + W256(0x52EA83C8,0xE4156040,0x0792FA4C,0x97CA4A43,0x3C9611E1,0x2198FE81,0x41AEAAE6,0x11919AD1), + W256(0x54A55516,0xCD8ADA8A,0x820A3D65,0xF85C2DB2,0x06667F3B,0xFF1E45F7,0x26BD6148,0x7F4E9D95), + W256(0xA4986374,0x2C1BF6DE,0x57ABC779,0x7C913D04,0xFA1127FA,0x1D7E8692,0xDE0E0680,0xC636320A) + } +}; diff --git a/source/extern/curve25519/source/ed25519_sign.c b/source/extern/curve25519/source/ed25519_sign.c new file mode 100644 index 0000000..8d3aa1c --- /dev/null +++ b/source/extern/curve25519/source/ed25519_sign.c @@ -0,0 +1,419 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2015 mehdi sotoodeh + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "../include/external_calls.h" +#include "curve25519_mehdi.h" +#include "../include/ed25519_signature.h" +#include "sha512.h" + +/* + * Arithmetic on twisted Edwards curve y^2 - x^2 = 1 + dx^2y^2 + * with d = -(121665/121666) mod p + * d = 0x52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3 + * p = 2**255 - 19 + * p = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED + * Base point: y=4/5 mod p + * x = 0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A + * y = 0x6666666666666666666666666666666666666666666666666666666666666658 + * Base point order: + * l = 2**252 + 27742317777372353535851937790883648493 + * l = 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED + */ + +extern const U_WORD _w_maxP[K_WORDS]; +extern const U_WORD _w_NxBPO[16][K_WORDS]; + +#define _w_BPO _w_NxBPO[1] + +/* +// -- custom blind --------------------------------------------------------- +// +// edp_custom_blinding is defined in source/custom_blind.c +// source/custom_blind is created randomly on every new build +// +// ------------------------------------------------------------------------- +*/ +extern EDP_BLINDING_CTX edp_custom_blinding; + +const U_WORD _w_2d[K_WORDS] = /* 2*d */ + W256(0x26B2F159,0xEBD69B94,0x8283B156,0x00E0149A,0xEEF3D130,0x198E80F2,0x56DFFCE7,0x2406D9DC); +const U_WORD _w_di[K_WORDS] = /* 1/d */ + W256(0xCDC9F843,0x25E0F276,0x4279542E,0x0B5DD698,0xCDB9CF66,0x2B162114,0x14D5CE43,0x40907ED2); + +#include "base_folding8.h" + +/* + Reference: http://eprint.iacr.org/2008/522 + Cost: 7M + 7add + Return: R = P + BasePoint +*/ +void edp_AddBasePoint(Ext_POINT *p) +{ + U_WORD a[K_WORDS], b[K_WORDS], c[K_WORDS], d[K_WORDS], e[K_WORDS]; + + ecp_SubReduce(a, p->y, p->x); /* A = (Y1-X1)*(Y2-X2) */ + ecp_MulReduce(a, a, _w_base_folding8[1].YmX); + ecp_AddReduce(b, p->y, p->x); /* B = (Y1+X1)*(Y2+X2) */ + ecp_MulReduce(b, b, _w_base_folding8[1].YpX); + ecp_MulReduce(c, p->t, _w_base_folding8[1].T2d); /* C = T1*2d*T2 */ + ecp_AddReduce(d, p->z, p->z); /* D = 2*Z1 */ + ecp_SubReduce(e, b, a); /* E = B-A */ + ecp_AddReduce(b, b, a); /* H = B+A */ + ecp_SubReduce(a, d, c); /* F = D-C */ + ecp_AddReduce(d, d, c); /* G = D+C */ + + ecp_MulReduce(p->x, e, a); /* E*F */ + ecp_MulReduce(p->y, b, d); /* H*G */ + ecp_MulReduce(p->t, e, b); /* E*H */ + ecp_MulReduce(p->z, d, a); /* G*F */ +} + +/* + Assumptions: pre-computed q, q->Z=1 + Cost: 7M + 7add + Return: P = P + Q +*/ +void edp_AddAffinePoint(Ext_POINT *p, const PA_POINT *q) +{ + U_WORD a[K_WORDS], b[K_WORDS], c[K_WORDS], d[K_WORDS], e[K_WORDS]; + ecp_SubReduce(a, p->y, p->x); /* A = (Y1-X1)*(Y2-X2) */ + ecp_MulReduce(a, a, q->YmX); + ecp_AddReduce(b, p->y, p->x); /* B = (Y1+X1)*(Y2+X2) */ + ecp_MulReduce(b, b, q->YpX); + ecp_MulReduce(c, p->t, q->T2d); /* C = T1*2d*T2 */ + ecp_AddReduce(d, p->z, p->z); /* D = Z1*2*Z2 (Z2=1)*/ + ecp_SubReduce(e, b, a); /* E = B-A */ + ecp_AddReduce(b, b, a); /* H = B+A */ + ecp_SubReduce(a, d, c); /* F = D-C */ + ecp_AddReduce(d, d, c); /* G = D+C */ + + ecp_MulReduce(p->x, e, a); /* E*F */ + ecp_MulReduce(p->y, b, d); /* H*G */ + ecp_MulReduce(p->t, e, b); /* E*H */ + ecp_MulReduce(p->z, d, a); /* G*F */ +} + +/* + Reference: http://eprint.iacr.org/2008/522 + Cost: 4M + 4S + 7add + Return: P = 2*P +*/ +void edp_DoublePoint(Ext_POINT *p) +{ + U_WORD a[K_WORDS], b[K_WORDS], c[K_WORDS], d[K_WORDS], e[K_WORDS]; + + ecp_SqrReduce(a, p->x); /* A = X1^2 */ + ecp_SqrReduce(b, p->y); /* B = Y1^2 */ + ecp_SqrReduce(c, p->z); /* C = 2*Z1^2 */ + ecp_AddReduce(c, c, c); + ecp_SubReduce(d, _w_maxP, a); /* D = -A */ + + ecp_SubReduce(a, d, b); /* H = D-B */ + ecp_AddReduce(d, d, b); /* G = D+B */ + ecp_SubReduce(b, d, c); /* F = G-C */ + ecp_AddReduce(e, p->x, p->y); /* E = (X1+Y1)^2-A-B = (X1+Y1)^2+H */ + ecp_SqrReduce(e, e); + ecp_AddReduce(e, e, a); + + ecp_MulReduce(p->x, e, b); /* E*F */ + ecp_MulReduce(p->y, a, d); /* H*G */ + ecp_MulReduce(p->z, d, b); /* G*F */ + ecp_MulReduce(p->t, e, a); /* E*H */ +} + +/* -- FOLDING --------------------------------------------------------------- +// +// The performance boost is achieved by a process that I call it FOLDING. +// Folding can be viewed as an extension of Shamir's trick but it is based +// on break down of the scalar multiplier of a*P into a polynomial of the +// form: +// +// a*P = SUM(a_i*2^(i*w))*P for i = 0,1,2,...n-1 +// +// a*P = SUM(a_i*P_i) +// +// where P_i = (2^(i*w))*P +// n = number of folds +// w = bit-length of a_i +// +// For folding of 8, 256-bit multiplier 'a' is chopped into 8 limbs of +// 32-bits each (a_0, a_1,...a_7). P_0 - P_7 can be pre-calculated and +// their 256-different permutations can be cached or hard-coded +// directly into the code. +// This arrangement combined with double-and-add approach reduces the +// number of EC point calculations by a factor of 8. We only need 31 +// double & add operations. +// +// +---+---+---+---+---+---+- .... -+---+---+---+---+---+---+ +// a = (|255|254|253|252|251|250| | 5 | 4 | 3 | 2 | 1 | 0 |) +// +---+---+---+---+---+---+- .... -+---+---+---+---+---+---+ +// +// a_i P_i +// +---+---+---+ .... -+---+---+---+ ---------- +// a7 = (|255|254|253| |226|225|224|) * (2**224)*P +// +---+---+---+ .... -+---+---+---+ +// a6 = (|225|224|223| |194|193|192|) * (2**192)*P +// +---+---+---+ .... -+---+---+---+ +// a5 = (|191|190|189| |162|161|160|) * (2**160)*P +// +---+---+---+ .... -+---+---+---+ +// a4 = (|159|158|157| |130|129|128|) * (2**128)*P +// +---+---+---+ .... -+---+---+---+ +// a3 = (|127|126|125| | 98| 97| 96|) * (2**96)*P +// +---+---+---+ .... -+---+---+---+ +// a2 = (| 95| 94| 93| | 66| 65| 64|) * (2**64)*P +// +---+---+---+ .... -+---+---+---+ +// a1 = (| 63| 62| 61| | 34| 33| 32|) * (2**32)*P +// +---+---+---+ .... -+---+---+---+ +// a0 = (| 31| 30| 29| | 2 | 1 | 0 |) * (2**0)*P +// +---+---+---+ .... -+---+---+---+ +// | | | | +// | +--+ | +--+ +// | | | | +// V V slices V V +// +---+ +---+ .... +---+ +---+ +// |255| |254| |225| |224| P7 +// +---+ +---+ .... +---+ +---+ +// |225| |224| |193| |192| P6 +// +---+ +---+ .... +---+ +---+ +// |191| |190| |161| |160| P5 +// +---+ +---+ .... +---+ +---+ +// |159| |158| |129| |128| P4 +// +---+ +---+ .... +---+ +---+ +// |127| |126| | 97| | 96| P3 +// +---+ +---+ .... +---+ +---+ +// | 95| | 94| | 65| | 64| P2 +// +---+ +---+ .... +---+ +---+ +// | 63| | 62| | 33| | 32| P1 +// +---+ +---+ .... +---+ +---+ +// | 31| | 30| | 1 | | 0 | P0 +// +---+ +---+ .... +---+ +---+ +// cut[]: 0 1 .... 30 31 +// -------------------------------------------------------------------------- +// Return S = a*P where P is ed25519 base point and R is random +*/ +void edp_BasePointMult( + OUT Ext_POINT *S, + IN const U_WORD *sk, + IN const U_WORD *R) +{ + int i = 1; + U8 cut[32]; + const PA_POINT *p0; + + ecp_8Folds(cut, sk); + + p0 = &_w_base_folding8[cut[0]]; + + ecp_SubReduce(S->x, p0->YpX, p0->YmX); /* 2x */ + ecp_AddReduce(S->y, p0->YpX, p0->YmX); /* 2y */ + ecp_MulReduce(S->t, p0->T2d, _w_di); /* 2xy */ + + /* Randomize starting point */ + + ecp_AddReduce(S->z, R, R); /* Z = 2R */ + ecp_MulReduce(S->x, S->x, R); /* X = 2xR */ + ecp_MulReduce(S->t, S->t, R); /* T = 2xyR */ + ecp_MulReduce(S->y, S->y, R); /* Y = 2yR */ + + do + { + edp_DoublePoint(S); + edp_AddAffinePoint(S, &_w_base_folding8[cut[i]]); + } while (i++ < 31); +} + +void edp_BasePointMultiply( + OUT Affine_POINT *R, + IN const U_WORD *sk, + IN const void *blinding) +{ + Ext_POINT S; + U_WORD t[K_WORDS]; + + if (blinding) + { + eco_AddReduce(t, sk, ((EDP_BLINDING_CTX*)blinding)->bl); + edp_BasePointMult(&S, t, ((EDP_BLINDING_CTX*)blinding)->zr); + edp_AddPoint(&S, &S, &((EDP_BLINDING_CTX*)blinding)->BP); + } + else + { + edp_BasePointMult(&S, sk, edp_custom_blinding.zr); + } + + ecp_Inverse(S.z, S.z); + ecp_MulMod(R->x, S.x, S.z); + ecp_MulMod(R->y, S.y, S.z); +} + +void edp_ExtPoint2PE(PE_POINT *r, const Ext_POINT *p) +{ + ecp_AddReduce(r->YpX, p->y, p->x); + ecp_SubReduce(r->YmX, p->y, p->x); + ecp_MulReduce(r->T2d, p->t, _w_2d); + ecp_AddReduce(r->Z2, p->z, p->z); +} + +/* -- Blinding ------------------------------------------------------------- +// +// Blinding is a measure to protect against side channel attacks. +// Blinding randomizes the scalar multiplier. +// +// Instead of calculating a*P, calculate (a+b mod BPO)*P + B +// +// Where b = random blinding and B = -b*P +// +// ------------------------------------------------------------------------- +*/ +void *ed25519_Blinding_Init( + void *context, /* IO: null or ptr blinding context */ + const unsigned char *seed, /* IN: [size bytes] random blinding seed */ + size_t size) /* IN: size of blinding seed */ +{ + struct { + Ext_POINT T; + U_WORD t[K_WORDS]; + SHA512_CTX H; + U8 digest[SHA512_DIGEST_LENGTH]; + } d; + + EDP_BLINDING_CTX *ctx = (EDP_BLINDING_CTX*)context; + + if (ctx == 0) + { + ctx = (EDP_BLINDING_CTX*)mem_alloc(sizeof(EDP_BLINDING_CTX)); + if (ctx == 0) return 0; + } + + /* Use edp_custom_blinding to protect generation of the new blinder */ + + SHA512_Init(&d.H); + SHA512_Update(&d.H, edp_custom_blinding.zr, 32); + SHA512_Update(&d.H, seed, size); + SHA512_Final(d.digest, &d.H); + + ecp_BytesToWords(ctx->zr, d.digest+32); + ecp_BytesToWords(d.t, d.digest); + eco_Mod(d.t); + ecp_Sub(ctx->bl, _w_BPO, d.t); + + eco_AddReduce(d.t, d.t, edp_custom_blinding.bl); + edp_BasePointMult(&d.T, d.t, edp_custom_blinding.zr); + edp_AddPoint(&d.T, &d.T, &edp_custom_blinding.BP); + + edp_ExtPoint2PE(&ctx->BP, &d.T); + + /* clear potentially sensitive data */ + mem_clear (&d, sizeof(d)); + + return ctx; +} + +void ed25519_Blinding_Finish( + void *context) /* IN: blinding context */ +{ + if (context) + { + mem_clear (context, sizeof(EDP_BLINDING_CTX)); + mem_free (context); + } +} + +/* Generate public and private key pair associated with the secret key */ +void ed25519_CreateKeyPair( + unsigned char *pubKey, /* OUT: public key */ + unsigned char *privKey, /* OUT: private key */ + const void *blinding, /* IN: [optional] null or blinding context */ + const unsigned char *sk) /* IN: secret key (32 bytes) */ +{ + U8 md[SHA512_DIGEST_LENGTH]; + U_WORD t[K_WORDS]; + SHA512_CTX H; + Affine_POINT Q; + + /* [a:b] = H(sk) */ + SHA512_Init(&H); + SHA512_Update(&H, sk, 32); + SHA512_Final(md, &H); + ecp_TrimSecretKey(md); + + ecp_BytesToWords(t, md); + edp_BasePointMultiply(&Q, t, blinding); + ed25519_PackPoint(pubKey, Q.y, Q.x[0]); + + memcpy(privKey, sk, 32); + memcpy(privKey+32, pubKey, 32); +} + +/* + * Generate message signature + */ +void ed25519_SignMessage( + unsigned char *signature, /* OUT: [64 bytes] signature (R,S) */ + const unsigned char *privKey, /* IN: [64 bytes] private key (sk,pk) */ + const void *blinding, /* IN: [optional] null or blinding context */ + const unsigned char *msg, /* IN: [msg_size bytes] message to sign */ + size_t msg_size) +{ + SHA512_CTX H; + Affine_POINT R; + U_WORD a[K_WORDS], t[K_WORDS], r[K_WORDS]; + U8 md[SHA512_DIGEST_LENGTH]; + + /* [a:b] = H(sk) */ + SHA512_Init(&H); + SHA512_Update(&H, privKey, 32); + SHA512_Final(md, &H); + ecp_TrimSecretKey(md); /* a = first 32 bytes */ + ecp_BytesToWords(a, md); + + /* r = H(b + m) mod BPO */ + SHA512_Init(&H); + SHA512_Update(&H, md+32, 32); + SHA512_Update(&H, msg, msg_size); + SHA512_Final(md, &H); + eco_DigestToWords(r, md); + eco_Mod(r); /* r mod BPO */ + + /* R = r*P */ + edp_BasePointMultiply(&R, r, blinding); + ed25519_PackPoint(signature, R.y, R.x[0]); /* R part of signature */ + + /* S = r + H(encoded(R) + pk + m) * a mod BPO */ + SHA512_Init(&H); + SHA512_Update(&H, signature, 32); /* encoded(R) */ + SHA512_Update(&H, privKey+32, 32); /* pk */ + SHA512_Update(&H, msg, msg_size); /* m */ + SHA512_Final(md, &H); + eco_DigestToWords(t, md); + + eco_MulReduce(t, t, a); /* h()*a */ + eco_AddReduce(t, t, r); + eco_Mod(t); + ecp_WordsToBytes(signature+32, t); /* S part of signature */ + + /* Clear sensitive data */ + ecp_SetValue(a, 0); + ecp_SetValue(r, 0); +} diff --git a/source/extern/curve25519/source/ed25519_verify.c b/source/extern/curve25519/source/ed25519_verify.c new file mode 100644 index 0000000..fdd8c55 --- /dev/null +++ b/source/extern/curve25519/source/ed25519_verify.c @@ -0,0 +1,313 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2015 mehdi sotoodeh + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "../include/external_calls.h" +#include "curve25519_mehdi.h" +#include "../include/ed25519_signature.h" +#include "sha512.h" + +/* + * Arithmetic on twisted Edwards curve y^2 - x^2 = 1 + dx^2y^2 + * with d = -(121665/121666) mod p + * d = 0x52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3 + * p = 2**255 - 19 + * p = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED + * Base point: y=4/5 mod p + * x = 0x216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A + * y = 0x6666666666666666666666666666666666666666666666666666666666666658 + * Base point order: + * l = 2**252 + 27742317777372353535851937790883648493 + * l = 0x1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED + */ + +typedef struct { + unsigned char pk[32]; + PE_POINT q_table[16]; +} EDP_SIGV_CTX; + +extern const U_WORD _w_P[K_WORDS]; +extern const U_WORD _w_di[K_WORDS]; + +extern const PA_POINT _w_base_folding8[256]; +extern const U_WORD _w_NxBPO[16][K_WORDS]; + +#define _w_BPO _w_NxBPO[1] + +#define _w_Zero _w_base_folding8[0].T2d +#define _w_One _w_base_folding8[0].YpX + +const U_WORD _w_I[K_WORDS] = /* sqrt(-1) */ + W256(0x4A0EA0B0,0xC4EE1B27,0xAD2FE478,0x2F431806,0x3DFBD7A7,0x2B4D0099,0x4FC1DF0B,0x2B832480); + +static const U_WORD _w_d[K_WORDS] = + W256(0x135978A3,0x75EB4DCA,0x4141D8AB,0x00700A4D,0x7779E898,0x8CC74079,0x2B6FFE73,0x52036CEE); + +void ed25519_CalculateX(OUT U_WORD *X, IN const U_WORD *Y, U_WORD parity) +{ + U_WORD u[K_WORDS], v[K_WORDS], a[K_WORDS], b[K_WORDS]; + + /* Calculate sqrt((y^2 - 1)/(d*y^2 + 1)) */ + + ecp_SqrReduce(u, Y); /* u = y^2 */ + ecp_MulReduce(v, u, _w_d); /* v = dy^2 */ + ecp_SubReduce(u, u, _w_One); /* u = y^2-1 */ + ecp_AddReduce(v, v, _w_One); /* v = dy^2+1 */ + + /* Calculate: sqrt(u/v) = u*v^3 * (u*v^7)^((p-5)/8) */ + + ecp_SqrReduce(b, v); + ecp_MulReduce(a, u, b); + ecp_MulReduce(a, a, v); /* a = u*v^3 */ + ecp_SqrReduce(b, b); /* b = v^4 */ + ecp_MulReduce(b, a, b); /* b = u*v^7 */ + ecp_ModExp2523(b, b); + ecp_MulReduce(X, b, a); + + /* Check if we have correct sqrt, else, multiply by sqrt(-1) */ + + ecp_SqrReduce(b, X); + ecp_MulReduce(b, b, v); + ecp_SubReduce(b, b, u); + ecp_Mod(b); + if (ecp_CmpNE(b, _w_Zero)) ecp_MulReduce(X, X, _w_I); + + while (ecp_CmpLT(X, _w_P) == 0) ecp_Sub(X, X, _w_P); + + /* match parity */ + if (((X[0] ^ parity) & 1) != 0) + ecp_Sub(X, _w_P, X); +} + +void ed25519_UnpackPoint(Affine_POINT *r, const unsigned char *p) +{ + U8 parity = ecp_DecodeInt(r->y, p); + ed25519_CalculateX(r->x, r->y, parity); +} + +void ecp_SrqMulReduce(U_WORD *Z, const U_WORD *X, int n, const U_WORD *Y) +{ + U_WORD t[K_WORDS]; + ecp_SqrReduce(t, X); + while (n-- > 1) ecp_SqrReduce(t, t); + ecp_MulReduce(Z, t, Y); +} + +void ecp_ModExp2523(U_WORD *Y, const U_WORD *X) +{ + U_WORD x2[K_WORDS], x9[K_WORDS], x11[K_WORDS], x5[K_WORDS], x10[K_WORDS]; + U_WORD x20[K_WORDS], x50[K_WORDS], x100[K_WORDS], t[K_WORDS]; + + ecp_SqrReduce(x2, X); /* 2 */ + ecp_SrqMulReduce(x9, x2, 2, X); /* 9 */ + ecp_MulReduce(x11, x9, x2); /* 11 */ + ecp_SqrReduce(t, x11); /* 22 */ + ecp_MulReduce(x5, t, x9); /* 31 = 2^5 - 2^0 */ + ecp_SrqMulReduce(x10, x5, 5, x5); /* 2^10 - 2^0 */ + ecp_SrqMulReduce(x20, x10, 10, x10); /* 2^20 - 2^0 */ + ecp_SrqMulReduce(t, x20, 20, x20); /* 2^40 - 2^0 */ + ecp_SrqMulReduce(x50, t, 10, x10); /* 2^50 - 2^0 */ + ecp_SrqMulReduce(x100, x50, 50, x50); /* 2^100 - 2^0 */ + ecp_SrqMulReduce(t, x100, 100, x100); /* 2^200 - 2^0 */ + ecp_SrqMulReduce(t, t, 50, x50); /* 2^250 - 2^0 */ + ecp_SqrReduce(t, t); ecp_SqrReduce(t, t); /* 2^252 - 2^2 */ + ecp_MulReduce(Y, t, X); /* 2^252 - 3 */ +} + +/* + Assumptions: pre-computed q + Cost: 8M + 6add + Return: P = P + Q +*/ +void edp_AddPoint(Ext_POINT *r, const Ext_POINT *p, const PE_POINT *q) +{ + U_WORD a[K_WORDS], b[K_WORDS], c[K_WORDS], d[K_WORDS], e[K_WORDS]; + + ecp_SubReduce(a, p->y, p->x); /* A = (Y1-X1)*(Y2-X2) */ + ecp_MulReduce(a, a, q->YmX); + ecp_AddReduce(b, p->y, p->x); /* B = (Y1+X1)*(Y2+X2) */ + ecp_MulReduce(b, b, q->YpX); + ecp_MulReduce(c, p->t, q->T2d); /* C = T1*2d*T2 */ + ecp_MulReduce(d, p->z, q->Z2); /* D = Z1*2*Z2 */ + ecp_SubReduce(e, b, a); /* E = B-A */ + ecp_AddReduce(b, b, a); /* H = B+A */ + ecp_SubReduce(a, d, c); /* F = D-C */ + ecp_AddReduce(d, d, c); /* G = D+C */ + + ecp_MulReduce(r->x, e, a); /* E*F */ + ecp_MulReduce(r->y, b, d); /* H*G */ + ecp_MulReduce(r->t, e, b); /* E*H */ + ecp_MulReduce(r->z, d, a); /* G*F */ +} + +int ed25519_VerifySignature( + const unsigned char *signature, /* IN: signature (R,S) */ + const unsigned char *publicKey, /* IN: public key */ + const unsigned char *msg, size_t msg_size) /* IN: message to sign */ +{ + EDP_SIGV_CTX ctx; + + ed25519_Verify_Init(&ctx, publicKey); + + return ed25519_Verify_Check(&ctx, signature, msg, msg_size); +} + +#define QTABLE_SET(d,s) \ + edp_AddPoint(&T, &Q, &ctx->q_table[s]); \ + edp_ExtPoint2PE(&ctx->q_table[d], &T) + +void * ed25519_Verify_Init( + void *context, /* IO: null or context buffer to use */ + const unsigned char *publicKey) /* IN: [32 bytes] public key */ +{ + int i; + Ext_POINT Q, T; + EDP_SIGV_CTX *ctx = (EDP_SIGV_CTX*)context; + + if (ctx == 0) ctx = (EDP_SIGV_CTX*)mem_alloc(sizeof(EDP_SIGV_CTX)); + + if (ctx) + { + memcpy(ctx->pk, publicKey, 32); + i = ecp_DecodeInt(Q.y, publicKey); + ed25519_CalculateX(Q.x, Q.y, ~i); /* Invert parity for -Q */ + ecp_MulMod(Q.t, Q.x, Q.y); + ecp_SetValue(Q.z, 1); + + /* pre-compute q-table */ + + /* Calculate: Q0=Q, Q1=(2^64)*Q, Q2=(2^128)*Q, Q3=(2^192)*Q */ + + ecp_SetValue(ctx->q_table[0].YpX, 1); /* -- -- -- -- */ + ecp_SetValue(ctx->q_table[0].YmX, 1); + ecp_SetValue(ctx->q_table[0].T2d, 0); + ecp_SetValue(ctx->q_table[0].Z2, 2); + + edp_ExtPoint2PE(&ctx->q_table[1], &Q); /* -- -- -- q0 */ + + for (i = 0; i < 64; i++) edp_DoublePoint(&Q); + + edp_ExtPoint2PE(&ctx->q_table[2], &Q); /* -- -- q1 -- */ + QTABLE_SET(3,1); /* -- -- q1 q0 */ + + do edp_DoublePoint(&Q); while (++i < 128); + + edp_ExtPoint2PE(&ctx->q_table[4], &Q); /* -- q2 -- -- */ + QTABLE_SET(5, 1); /* -- q2 -- q0 */ + QTABLE_SET(6, 2); /* -- q2 q1 -- */ + QTABLE_SET(7, 3); /* -- q2 q1 q0 */ + + do edp_DoublePoint(&Q); while (++i < 192); + + edp_ExtPoint2PE(&ctx->q_table[8], &Q); /* q3 -- -- -- */ + QTABLE_SET(9, 1); /* q3 -- -- q0 */ + QTABLE_SET(10, 2); /* q3 -- q1 -- */ + QTABLE_SET(11, 3); /* q3 -- q1 q0 */ + QTABLE_SET(12, 4); /* q3 q2 -- -- */ + QTABLE_SET(13, 5); /* q3 q2 -- q0 */ + QTABLE_SET(14, 6); /* q3 q2 q1 -- */ + QTABLE_SET(15, 7); /* q3 q2 q1 q0 */ + } + return ctx; +} + +void ed25519_Verify_Finish(void *ctx) +{ + mem_free(ctx); +} + +/* + Assumptions: qtable = pre-computed Q + Calculate: point R = a*P + b*Q where P is base point +*/ +static void edp_PolyPointMultiply( + Affine_POINT *r, + const U_WORD *a, + const U_WORD *b, + const PE_POINT *qtable) +{ + int i = 1; + Ext_POINT S; + const PE_POINT *q0; + U8 u[32], v[64]; + + ecp_8Folds(u, a); + ecp_4Folds(v, b); + + /* Set initial value of S */ + q0 = &qtable[v[0]]; + ecp_SubReduce(S.x, q0->YpX, q0->YmX); /* 2x */ + ecp_AddReduce(S.y, q0->YpX, q0->YmX); /* 2y */ + ecp_MulReduce(S.t, q0->T2d, _w_di); /* 2xy */ + ecp_Copy(S.z, q0->Z2); /* 2z */ + + do + { /* 31D + 31A */ + edp_DoublePoint(&S); + edp_AddPoint(&S, &S, &qtable[v[i]]); + } while (++i < 32); + + do + { /* 32D + 64A */ + edp_DoublePoint(&S); + edp_AddAffinePoint(&S, &_w_base_folding8[u[i-32]]); + edp_AddPoint(&S, &S, &qtable[v[i]]); + } while (++i < 64); + + ecp_Inverse(S.z, S.z); + ecp_MulMod(r->x, S.x, S.z); + ecp_MulMod(r->y, S.y, S.z); +} + +/* + This function can be used for batch verification. + Assumptions: context = ed25519_Verify_Init(pk) + +*/ +int ed25519_Verify_Check( + const void *context, /* IN: precomputes */ + const unsigned char *signature, /* IN: signature (R,S) */ + const unsigned char *msg, size_t msg_size) /* IN: message to sign */ +{ + SHA512_CTX H; + Affine_POINT T; + U_WORD h[K_WORDS], s[K_WORDS]; + U8 md[SHA512_DIGEST_LENGTH]; + + /* h = H(enc(R) + pk + m) mod BPO */ + SHA512_Init(&H); + SHA512_Update(&H, signature, 32); /* enc(R) */ + SHA512_Update(&H, ((EDP_SIGV_CTX*)context)->pk, 32); + SHA512_Update(&H, msg, msg_size); + SHA512_Final(md, &H); + eco_DigestToWords(h, md); + eco_Mod(h); + + /* T = s*P + h*(-Q) = (s - h*a)*P = r*P = R */ + + ecp_BytesToWords(s, signature+32); + edp_PolyPointMultiply(&T, s, h, ((EDP_SIGV_CTX*)context)->q_table); + ed25519_PackPoint(md, T.y, T.x[0]); + + return (memcmp(md, signature, 32) == 0) ? 1 : 0; +} diff --git a/source/extern/curve25519/source/sha512.c b/source/extern/curve25519/source/sha512.c new file mode 100644 index 0000000..711cb32 --- /dev/null +++ b/source/extern/curve25519/source/sha512.c @@ -0,0 +1,294 @@ +/* crypto/sha/sha512.c */ +/* ==================================================================== + * Copyright (c) 2004 The OpenSSL Project. All rights reserved + * according to the OpenSSL license [found in ../../LICENSE]. + * ==================================================================== + */ +/* + * IMPLEMENTATION NOTES. + * + * As you might have noticed 32-bit hash algorithms: + * + * - permit SHA_LONG to be wider than 32-bit (case on CRAY); + * - optimized versions implement two transform functions: one operating + * on [aligned] data in host byte order and one - on data in input + * stream byte order; + * - share common byte-order neutral collector and padding function + * implementations, ../md32_common.h; + * + * Neither of the above applies to this SHA-512 implementations. Reasons + * [in reverse order] are: + * + * - it's the only 64-bit hash algorithm for the moment of this writing, + * there is no need for common collector/padding implementation [yet]; + * - by supporting only one transform function [which operates on + * *aligned* data in input stream byte order, big-endian in this case] + * we minimize burden of maintenance in two ways: a) collector/padding + * function is simpler; b) only one transform function to stare at; + * - SHA_LONG64 is required to be exactly 64-bit in order to be able to + * apply a number of optimizations to mitigate potential performance + * penalties caused by previous design decision; + * + * Caveat lector. + * + * Implementation relies on the fact that "long long" is 64-bit on + * both 32- and 64-bit platforms. If some compiler vendor comes up + * with 128-bit long long, adjustment to sha.h would be required. + * As this implementation relies on 64-bit integer type, it's totally + * inappropriate for platforms which don't support it, most notably + * 16-bit platforms. + * + */ +#include +#include "../include/external_calls.h" +#include "sha512.h" + +#define UINT64(X) X##ULL + +void SHA512_Transform (SHA512_CTX *ctx, const void *in); + +void SHA512_Init (SHA512_CTX *c) +{ + c->h[0]=UINT64(0x6a09e667f3bcc908); + c->h[1]=UINT64(0xbb67ae8584caa73b); + c->h[2]=UINT64(0x3c6ef372fe94f82b); + c->h[3]=UINT64(0xa54ff53a5f1d36f1); + c->h[4]=UINT64(0x510e527fade682d1); + c->h[5]=UINT64(0x9b05688c2b3e6c1f); + c->h[6]=UINT64(0x1f83d9abfb41bd6b); + c->h[7]=UINT64(0x5be0cd19137e2179); + + c->Nl=0; + c->Nh=0; + c->num=0; + c->md_len=SHA512_DIGEST_LENGTH; +} + +void SHA512_Final (unsigned char *md, SHA512_CTX *c) +{ + unsigned char *p=(unsigned char *)c->u.p; + size_t n=c->num; + + p[n]=0x80; /* There always is a room for one */ + n++; + if (n > (SHA512_CBLOCK-16)) + mem_fill (p+n,0,SHA512_CBLOCK-n), n=0, + SHA512_Transform (c,p); + + mem_fill (p+n,0,SHA512_CBLOCK-16-n); +#ifdef ECP_CONFIG_BIG_ENDIAN + c->u.d[SHA_LBLOCK-2] = c->Nh; + c->u.d[SHA_LBLOCK-1] = c->Nl; +#else + p[SHA512_CBLOCK-1] = (unsigned char)(c->Nl); + p[SHA512_CBLOCK-2] = (unsigned char)(c->Nl>>8); + p[SHA512_CBLOCK-3] = (unsigned char)(c->Nl>>16); + p[SHA512_CBLOCK-4] = (unsigned char)(c->Nl>>24); + p[SHA512_CBLOCK-5] = (unsigned char)(c->Nl>>32); + p[SHA512_CBLOCK-6] = (unsigned char)(c->Nl>>40); + p[SHA512_CBLOCK-7] = (unsigned char)(c->Nl>>48); + p[SHA512_CBLOCK-8] = (unsigned char)(c->Nl>>56); + p[SHA512_CBLOCK-9] = (unsigned char)(c->Nh); + p[SHA512_CBLOCK-10] = (unsigned char)(c->Nh>>8); + p[SHA512_CBLOCK-11] = (unsigned char)(c->Nh>>16); + p[SHA512_CBLOCK-12] = (unsigned char)(c->Nh>>24); + p[SHA512_CBLOCK-13] = (unsigned char)(c->Nh>>32); + p[SHA512_CBLOCK-14] = (unsigned char)(c->Nh>>40); + p[SHA512_CBLOCK-15] = (unsigned char)(c->Nh>>48); + p[SHA512_CBLOCK-16] = (unsigned char)(c->Nh>>56); +#endif + + SHA512_Transform (c,p); + + if (md) for (n=0; n < SHA512_DIGEST_LENGTH/8; n++) + { + M64 m; + m.u64 = c->h[n]; + *(md++) = m.u8.b7; + *(md++) = m.u8.b6; + *(md++) = m.u8.b5; + *(md++) = m.u8.b4; + *(md++) = m.u8.b3; + *(md++) = m.u8.b2; + *(md++) = m.u8.b1; + *(md++) = m.u8.b0; + } +} + +void SHA512_Update (SHA512_CTX *c, const void *_data, size_t len) +{ + SHA_LONG64 l; + unsigned char *p=c->u.p; + const unsigned char *data=(const unsigned char *)_data; + + if (len==0) return; + + l = (c->Nl+(((SHA_LONG64)len)<<3))&UINT64(0xffffffffffffffff); + if (l < c->Nl) c->Nh++; + if (sizeof(len)>=8) c->Nh+=(((SHA_LONG64)len)>>61); + c->Nl=l; + + if (c->num != 0) + { + size_t n = SHA512_CBLOCK - c->num; + + if (len < n) + { + memcpy (p+c->num,data,len), c->num += (unsigned int)len; + return; + } + else + { + memcpy (p+c->num,data,n), c->num = 0; + len-=n, data+=n; + SHA512_Transform (c,p); + } + } + + while (len >= SHA512_CBLOCK) + { + SHA512_Transform (c,data);//,len/SHA512_CBLOCK), + data += SHA512_CBLOCK; + len -= SHA512_CBLOCK; + } + + if (len != 0) + memcpy (p,data,len), c->num = (int)len; +} + +static const SHA_LONG64 K512[80] = +{ + UINT64(0x428a2f98d728ae22),UINT64(0x7137449123ef65cd), + UINT64(0xb5c0fbcfec4d3b2f),UINT64(0xe9b5dba58189dbbc), + UINT64(0x3956c25bf348b538),UINT64(0x59f111f1b605d019), + UINT64(0x923f82a4af194f9b),UINT64(0xab1c5ed5da6d8118), + UINT64(0xd807aa98a3030242),UINT64(0x12835b0145706fbe), + UINT64(0x243185be4ee4b28c),UINT64(0x550c7dc3d5ffb4e2), + UINT64(0x72be5d74f27b896f),UINT64(0x80deb1fe3b1696b1), + UINT64(0x9bdc06a725c71235),UINT64(0xc19bf174cf692694), + UINT64(0xe49b69c19ef14ad2),UINT64(0xefbe4786384f25e3), + UINT64(0x0fc19dc68b8cd5b5),UINT64(0x240ca1cc77ac9c65), + UINT64(0x2de92c6f592b0275),UINT64(0x4a7484aa6ea6e483), + UINT64(0x5cb0a9dcbd41fbd4),UINT64(0x76f988da831153b5), + UINT64(0x983e5152ee66dfab),UINT64(0xa831c66d2db43210), + UINT64(0xb00327c898fb213f),UINT64(0xbf597fc7beef0ee4), + UINT64(0xc6e00bf33da88fc2),UINT64(0xd5a79147930aa725), + UINT64(0x06ca6351e003826f),UINT64(0x142929670a0e6e70), + UINT64(0x27b70a8546d22ffc),UINT64(0x2e1b21385c26c926), + UINT64(0x4d2c6dfc5ac42aed),UINT64(0x53380d139d95b3df), + UINT64(0x650a73548baf63de),UINT64(0x766a0abb3c77b2a8), + UINT64(0x81c2c92e47edaee6),UINT64(0x92722c851482353b), + UINT64(0xa2bfe8a14cf10364),UINT64(0xa81a664bbc423001), + UINT64(0xc24b8b70d0f89791),UINT64(0xc76c51a30654be30), + UINT64(0xd192e819d6ef5218),UINT64(0xd69906245565a910), + UINT64(0xf40e35855771202a),UINT64(0x106aa07032bbd1b8), + UINT64(0x19a4c116b8d2d0c8),UINT64(0x1e376c085141ab53), + UINT64(0x2748774cdf8eeb99),UINT64(0x34b0bcb5e19b48a8), + UINT64(0x391c0cb3c5c95a63),UINT64(0x4ed8aa4ae3418acb), + UINT64(0x5b9cca4f7763e373),UINT64(0x682e6ff3d6b2b8a3), + UINT64(0x748f82ee5defb2fc),UINT64(0x78a5636f43172f60), + UINT64(0x84c87814a1f0ab72),UINT64(0x8cc702081a6439ec), + UINT64(0x90befffa23631e28),UINT64(0xa4506cebde82bde9), + UINT64(0xbef9a3f7b2c67915),UINT64(0xc67178f2e372532b), + UINT64(0xca273eceea26619c),UINT64(0xd186b8c721c0c207), + UINT64(0xeada7dd6cde0eb1e),UINT64(0xf57d4f7fee6ed178), + UINT64(0x06f067aa72176fba),UINT64(0x0a637dc5a2c898a6), + UINT64(0x113f9804bef90dae),UINT64(0x1b710b35131c471b), + UINT64(0x28db77f523047d84),UINT64(0x32caab7b40c72493), + UINT64(0x3c9ebe0a15c9bebc),UINT64(0x431d67c49c100d4c), + UINT64(0x4cc5d4becb3e42b6),UINT64(0x597f299cfc657e2a), + UINT64(0x5fcb6fab3ad6faec),UINT64(0x6c44198c4a475817) +}; + +#define B(x,j) (((SHA_LONG64)(*(((const unsigned char *)(&x))+j)))<<((7-j)*8)) +#define PULL64(x) (B(x,0)|B(x,1)|B(x,2)|B(x,3)|B(x,4)|B(x,5)|B(x,6)|B(x,7)) +#define ROTR(x,s) (((x)>>s) | (x)<<(64-s)) + +#define Sigma0(x) (ROTR((x),28) ^ ROTR((x),34) ^ ROTR((x),39)) +#define Sigma1(x) (ROTR((x),14) ^ ROTR((x),18) ^ ROTR((x),41)) +#define sigma0(x) (ROTR((x),1) ^ ROTR((x),8) ^ ((x)>>7)) +#define sigma1(x) (ROTR((x),19) ^ ROTR((x),61) ^ ((x)>>6)) + +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +#define ROUND_00_15(i,a,b,c,d,e,f,g,h) do { \ + T1 += h + Sigma1(e) + Ch(e,f,g) + K512[i]; \ + h = Sigma0(a) + Maj(a,b,c); \ + d += T1; h += T1; } while (0) + +#define ROUND_16_80(i,j,a,b,c,d,e,f,g,h,X) do { \ + s0 = X[(j+1)&0x0f]; s0 = sigma0(s0); \ + s1 = X[(j+14)&0x0f]; s1 = sigma1(s1); \ + T1 = X[(j)&0x0f] += s0 + s1 + X[(j+9)&0x0f]; \ + ROUND_00_15(i+j,a,b,c,d,e,f,g,h); } while (0) + +void SHA512_Transform (SHA512_CTX *ctx, const void *in) +{ + const SHA_LONG64 *W = (SHA_LONG64*)in; + SHA_LONG64 a,b,c,d,e,f,g,h,s0,s1,T1; + SHA_LONG64 X[16]; + int i; + + a = ctx->h[0]; b = ctx->h[1]; c = ctx->h[2]; d = ctx->h[3]; + e = ctx->h[4]; f = ctx->h[5]; g = ctx->h[6]; h = ctx->h[7]; + +#ifdef ECP_CONFIG_BIG_ENDIAN + T1 = X[0] = W[0]; ROUND_00_15(0,a,b,c,d,e,f,g,h); + T1 = X[1] = W[1]; ROUND_00_15(1,h,a,b,c,d,e,f,g); + T1 = X[2] = W[2]; ROUND_00_15(2,g,h,a,b,c,d,e,f); + T1 = X[3] = W[3]; ROUND_00_15(3,f,g,h,a,b,c,d,e); + T1 = X[4] = W[4]; ROUND_00_15(4,e,f,g,h,a,b,c,d); + T1 = X[5] = W[5]; ROUND_00_15(5,d,e,f,g,h,a,b,c); + T1 = X[6] = W[6]; ROUND_00_15(6,c,d,e,f,g,h,a,b); + T1 = X[7] = W[7]; ROUND_00_15(7,b,c,d,e,f,g,h,a); + T1 = X[8] = W[8]; ROUND_00_15(8,a,b,c,d,e,f,g,h); + T1 = X[9] = W[9]; ROUND_00_15(9,h,a,b,c,d,e,f,g); + T1 = X[10] = W[10]; ROUND_00_15(10,g,h,a,b,c,d,e,f); + T1 = X[11] = W[11]; ROUND_00_15(11,f,g,h,a,b,c,d,e); + T1 = X[12] = W[12]; ROUND_00_15(12,e,f,g,h,a,b,c,d); + T1 = X[13] = W[13]; ROUND_00_15(13,d,e,f,g,h,a,b,c); + T1 = X[14] = W[14]; ROUND_00_15(14,c,d,e,f,g,h,a,b); + T1 = X[15] = W[15]; ROUND_00_15(15,b,c,d,e,f,g,h,a); +#else + T1 = X[0] = PULL64(W[0]); ROUND_00_15(0,a,b,c,d,e,f,g,h); + T1 = X[1] = PULL64(W[1]); ROUND_00_15(1,h,a,b,c,d,e,f,g); + T1 = X[2] = PULL64(W[2]); ROUND_00_15(2,g,h,a,b,c,d,e,f); + T1 = X[3] = PULL64(W[3]); ROUND_00_15(3,f,g,h,a,b,c,d,e); + T1 = X[4] = PULL64(W[4]); ROUND_00_15(4,e,f,g,h,a,b,c,d); + T1 = X[5] = PULL64(W[5]); ROUND_00_15(5,d,e,f,g,h,a,b,c); + T1 = X[6] = PULL64(W[6]); ROUND_00_15(6,c,d,e,f,g,h,a,b); + T1 = X[7] = PULL64(W[7]); ROUND_00_15(7,b,c,d,e,f,g,h,a); + T1 = X[8] = PULL64(W[8]); ROUND_00_15(8,a,b,c,d,e,f,g,h); + T1 = X[9] = PULL64(W[9]); ROUND_00_15(9,h,a,b,c,d,e,f,g); + T1 = X[10] = PULL64(W[10]); ROUND_00_15(10,g,h,a,b,c,d,e,f); + T1 = X[11] = PULL64(W[11]); ROUND_00_15(11,f,g,h,a,b,c,d,e); + T1 = X[12] = PULL64(W[12]); ROUND_00_15(12,e,f,g,h,a,b,c,d); + T1 = X[13] = PULL64(W[13]); ROUND_00_15(13,d,e,f,g,h,a,b,c); + T1 = X[14] = PULL64(W[14]); ROUND_00_15(14,c,d,e,f,g,h,a,b); + T1 = X[15] = PULL64(W[15]); ROUND_00_15(15,b,c,d,e,f,g,h,a); +#endif + + for (i=16;i<80;i+=16) + { + ROUND_16_80(i, 0,a,b,c,d,e,f,g,h,X); + ROUND_16_80(i, 1,h,a,b,c,d,e,f,g,X); + ROUND_16_80(i, 2,g,h,a,b,c,d,e,f,X); + ROUND_16_80(i, 3,f,g,h,a,b,c,d,e,X); + ROUND_16_80(i, 4,e,f,g,h,a,b,c,d,X); + ROUND_16_80(i, 5,d,e,f,g,h,a,b,c,X); + ROUND_16_80(i, 6,c,d,e,f,g,h,a,b,X); + ROUND_16_80(i, 7,b,c,d,e,f,g,h,a,X); + ROUND_16_80(i, 8,a,b,c,d,e,f,g,h,X); + ROUND_16_80(i, 9,h,a,b,c,d,e,f,g,X); + ROUND_16_80(i,10,g,h,a,b,c,d,e,f,X); + ROUND_16_80(i,11,f,g,h,a,b,c,d,e,X); + ROUND_16_80(i,12,e,f,g,h,a,b,c,d,X); + ROUND_16_80(i,13,d,e,f,g,h,a,b,c,X); + ROUND_16_80(i,14,c,d,e,f,g,h,a,b,X); + ROUND_16_80(i,15,b,c,d,e,f,g,h,a,X); + } + + ctx->h[0] += a; ctx->h[1] += b; ctx->h[2] += c; ctx->h[3] += d; + ctx->h[4] += e; ctx->h[5] += f; ctx->h[6] += g; ctx->h[7] += h; +} \ No newline at end of file diff --git a/source/extern/curve25519/source/sha512.h b/source/extern/curve25519/source/sha512.h new file mode 100644 index 0000000..675ee4c --- /dev/null +++ b/source/extern/curve25519/source/sha512.h @@ -0,0 +1,92 @@ +/* crypto/sha/sha512.h */ +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) + * All rights reserved. + * + * This package is an SSL implementation written + * by Eric Young (eay@cryptsoft.com). + * The implementation was written so as to conform with Netscapes SSL. + * + * This library is free for commercial and non-commercial use as long as + * the following conditions are aheared to. The following conditions + * apply to all code found in this distribution, be it the RC4, RSA, + * lhash, DES, etc., code; not just the SSL code. The SSL documentation + * included with this distribution is covered by the same copyright terms + * except that the holder is Tim Hudson (tjh@cryptsoft.com). + * + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * If this package is used in a product, Eric Young should be given attribution + * as the author of the parts of the library used. + * This can be in the form of a textual message at program startup or + * in documentation (online or textual) provided with the package. + * + * 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 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 acknowledgement: + * "This product includes cryptographic software written by + * Eric Young (eay@cryptsoft.com)" + * The word 'cryptographic' can be left out if the rouines from the library + * being used are not cryptographic related :-). + * 4. If you include any Windows specific code (or a derivative thereof) from + * the apps directory (application code) you must include an acknowledgement: + * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" + * + * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 AUTHOR 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. + * + * The licence and distribution terms for any publically available version or + * derivative of this code cannot be changed. i.e. this code cannot simply be + * copied and put under another distribution licence + * [including the GNU Public Licence.] + */ + +#ifndef HEADER_SHA512_H +#define HEADER_SHA512_H + +#include "BaseTypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_CBLOCK 128 /* SHA-512 treats input data as a + * contiguous array of 64 bit + * wide big-endian values. */ +#define SHA_LONG64 U64 + +typedef struct SHA512state_st +{ + SHA_LONG64 h[8]; + SHA_LONG64 Nl,Nh; + union { + SHA_LONG64 d[8]; + unsigned char p[SHA512_CBLOCK]; + } u; + unsigned int num, md_len; +} SHA512_CTX; + +void SHA512_Init(SHA512_CTX *c); +void SHA512_Update(SHA512_CTX *c, const void *data, size_t len); +void SHA512_Final(unsigned char *md, SHA512_CTX *c); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file