From bd73fb166ff333093ce18c4fdd9b50e636795d49 Mon Sep 17 00:00:00 2001 From: Novikov Valerii Date: Wed, 14 Feb 2024 01:52:59 +0500 Subject: [PATCH 1/8] Added Streebog-256/512 hash function as specified by GOST R 34.11-2012 --- core/crypto.h | 14 + hash/hash_algorithms.h | 16 + hash/streebog.c | 1272 ++++++++++++++++++++++++++++++++++++++++ hash/streebog.h | 127 ++++ 4 files changed, 1429 insertions(+) create mode 100644 hash/streebog.c create mode 100644 hash/streebog.h diff --git a/core/crypto.h b/core/crypto.h index d3e53296..05cb6e78 100644 --- a/core/crypto.h +++ b/core/crypto.h @@ -340,6 +340,20 @@ #error WHIRLPOOL_SUPPORT parameter is not valid #endif +//Streebog-256 hash support +#ifndef STREEBOG256_SUPPORT +#define STREEBOG256_SUPPORT DISABLED +#elif (STREEBOG256_SUPPORT != ENABLED && STREEBOG256_SUPPORT != DISABLED) +#error STREEBOG256_SUPPORT parameter is not valid +#endif + +//Streebog-512 hash support +#ifndef STREEBOG512_SUPPORT +#define STREEBOG512_SUPPORT DISABLED +#elif (STREEBOG512_SUPPORT != ENABLED && STREEBOG512_SUPPORT != DISABLED) +#error STREEBOG512_SUPPORT parameter is not valid +#endif + //CMAC support #ifndef CMAC_SUPPORT #define CMAC_SUPPORT DISABLED diff --git a/hash/hash_algorithms.h b/hash/hash_algorithms.h index 52134859..f0978bc9 100644 --- a/hash/hash_algorithms.h +++ b/hash/hash_algorithms.h @@ -169,6 +169,11 @@ #include "hash/whirlpool.h" #endif +//Streebog hash support? +#if (STREEBOG256_SUPPORT == ENABLED || STREEBOG512_SUPPORT == ENABLED) +#include "hash/streebog.h" +#endif + //Maximum block size #if (SHA3_224_SUPPORT == ENABLED) #define MAX_HASH_BLOCK_SIZE SHA3_224_BLOCK_SIZE @@ -218,6 +223,10 @@ #define MAX_HASH_BLOCK_SIZE RIPEMD160_BLOCK_SIZE #elif (RIPEMD128_SUPPORT == ENABLED) #define MAX_HASH_BLOCK_SIZE RIPEMD128_BLOCK_SIZE +#elif (STREEBOG512_SUPPORT == ENABLED) + #define MAX_HASH_BLOCK_SIZE STREEBOG_BLOCK_SIZE +#elif (STREEBOG256_SUPPORT == ENABLED) + #define MAX_HASH_BLOCK_SIZE STREEBOG_BLOCK_SIZE #elif (MD5_SUPPORT == ENABLED) #define MAX_HASH_BLOCK_SIZE MD5_BLOCK_SIZE #elif (MD4_SUPPORT == ENABLED) @@ -235,6 +244,8 @@ #define MAX_HASH_DIGEST_SIZE SHA3_512_DIGEST_SIZE #elif (SHA512_SUPPORT == ENABLED) #define MAX_HASH_DIGEST_SIZE SHA512_DIGEST_SIZE +#elif (STREEBOG512_SUPPORT == ENABLED) + #define MAX_HASH_DIGEST_SIZE STREEBOG512_DIGEST_SIZE #elif (BLAKE2B384_SUPPORT == ENABLED) #define MAX_HASH_DIGEST_SIZE BLAKE2B384_DIGEST_SIZE #elif (SHA3_384_SUPPORT == ENABLED) @@ -251,6 +262,8 @@ #define MAX_HASH_DIGEST_SIZE SHA512_256_DIGEST_SIZE #elif (SHA256_SUPPORT == ENABLED) #define MAX_HASH_DIGEST_SIZE SHA256_DIGEST_SIZE +#elif (STREEBOG256_SUPPORT == ENABLED) +#define MAX_HASH_DIGEST_SIZE STREEBOG256_DIGEST_SIZE #elif (SM3_SUPPORT == ENABLED) #define MAX_HASH_DIGEST_SIZE SM3_DIGEST_SIZE #elif (BLAKE2S224_SUPPORT == ENABLED) @@ -377,6 +390,9 @@ typedef union #if (WHIRLPOOL_SUPPORT == ENABLED) WhirlpoolContext whirlpoolContext; #endif +#if (STREEBOG512_SUPPORT == ENABLED || STREEBOG256_SUPPORT == ENABLED) + StreebogContext streebogContext; +#endif } HashContext; diff --git a/hash/streebog.c b/hash/streebog.c new file mode 100644 index 00000000..62c403ab --- /dev/null +++ b/hash/streebog.c @@ -0,0 +1,1272 @@ +/** + * @file streebog.c + * @brief Streebog-256/512 hash function + * + * Streebog-256/512 hash function as specified by GOST R 34.11-2012 and + * described at https://tools.ietf.org/html/rfc6986 + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2013 Alexey Degtyarev + * Copyright (c) 2018 Vitaly Chikunov + * Copyright (c) 2024 Valery Novikov + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Valery Novikov + * @version 2.4.0 + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL CRYPTO_TRACE_LEVEL + +//Dependencies +#include "core/crypto.h" +#include "hash/streebog.h" + +//Check crypto library configuration +#if (STREEBOG256_SUPPORT == ENABLED || STREEBOG512_SUPPORT == ENABLED) + +#if (STREEBOG256_SUPPORT == ENABLED) +//Streebog-256 object identifier (1.2.643.7.1.1.2.2) */ /* Generate by https://misc.daniel-marschall.de/asn.1/oid-converter/online.php */ +const uint8_t STREEBOG256_OID[10] = { 0x06, 0x08, 0x2A, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x02 }; + +//Common interface for hash algorithms +const HashAlgo streebog256HashAlgo = +{ + "Streebog-256", + STREEBOG256_OID, + sizeof(STREEBOG256_OID), + sizeof(StreebogContext), + STREEBOG_BLOCK_SIZE, + STREEBOG256_DIGEST_SIZE, + STREEBOG256_MIN_PAD_SIZE, + TRUE, + (HashAlgoCompute)streebog256Compute, + (HashAlgoInit)streebog256Init, + (HashAlgoUpdate)streebogUpdate, + (HashAlgoFinal)streebogFinal, + NULL +}; +#endif + +#if (STREEBOG512_SUPPORT == ENABLED) +//Streebog-256 object identifier (1.2.643.7.1.1.2.3) */ /* Generate by https://misc.daniel-marschall.de/asn.1/oid-converter/online.php */ +const uint8_t STREEBOG512_OID[10] = { 0x06, 0x08, 0x2A, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x03 }; + +//Common interface for hash algorithms +const HashAlgo streebog512HashAlgo = +{ + "Streebog-512", + STREEBOG512_OID, + sizeof(STREEBOG512_OID), + sizeof(StreebogContext), + STREEBOG_BLOCK_SIZE, + STREEBOG512_DIGEST_SIZE, + STREEBOG512_MIN_PAD_SIZE, + TRUE, + (HashAlgoCompute)streebog512Compute, + (HashAlgoInit)streebog512Init, + (HashAlgoUpdate)streebogUpdate, + (HashAlgoFinal)streebogFinal, + NULL +}; +#endif + +static const struct streebog_uint512 buffer0 = { { + 0, 0, 0, 0, 0, 0, 0, 0 +} }; + +static const struct streebog_uint512 buffer512 = { { + htole64(0x200), 0, 0, 0, 0, 0, 0, 0 +} }; + + +static const struct streebog_uint512 C[12] = { + { { + htole64(0xdd806559f2a64507ULL), + htole64(0x05767436cc744d23ULL), + htole64(0xa2422a08a460d315ULL), + htole64(0x4b7ce09192676901ULL), + htole64(0x714eb88d7585c4fcULL), + htole64(0x2f6a76432e45d016ULL), + htole64(0xebcb2f81c0657c1fULL), + htole64(0xb1085bda1ecadae9ULL) + } }, + { { + htole64(0xe679047021b19bb7ULL), + htole64(0x55dda21bd7cbcd56ULL), + htole64(0x5cb561c2db0aa7caULL), + htole64(0x9ab5176b12d69958ULL), + htole64(0x61d55e0f16b50131ULL), + htole64(0xf3feea720a232b98ULL), + htole64(0x4fe39d460f70b5d7ULL), + htole64(0x6fa3b58aa99d2f1aULL) + } }, + { { + htole64(0x991e96f50aba0ab2ULL), + htole64(0xc2b6f443867adb31ULL), + htole64(0xc1c93a376062db09ULL), + htole64(0xd3e20fe490359eb1ULL), + htole64(0xf2ea7514b1297b7bULL), + htole64(0x06f15e5f529c1f8bULL), + htole64(0x0a39fc286a3d8435ULL), + htole64(0xf574dcac2bce2fc7ULL) + } }, + { { + htole64(0x220cbebc84e3d12eULL), + htole64(0x3453eaa193e837f1ULL), + htole64(0xd8b71333935203beULL), + htole64(0xa9d72c82ed03d675ULL), + htole64(0x9d721cad685e353fULL), + htole64(0x488e857e335c3c7dULL), + htole64(0xf948e1a05d71e4ddULL), + htole64(0xef1fdfb3e81566d2ULL) + } }, + { { + htole64(0x601758fd7c6cfe57ULL), + htole64(0x7a56a27ea9ea63f5ULL), + htole64(0xdfff00b723271a16ULL), + htole64(0xbfcd1747253af5a3ULL), + htole64(0x359e35d7800fffbdULL), + htole64(0x7f151c1f1686104aULL), + htole64(0x9a3f410c6ca92363ULL), + htole64(0x4bea6bacad474799ULL) + } }, + { { + htole64(0xfa68407a46647d6eULL), + htole64(0xbf71c57236904f35ULL), + htole64(0x0af21f66c2bec6b6ULL), + htole64(0xcffaa6b71c9ab7b4ULL), + htole64(0x187f9ab49af08ec6ULL), + htole64(0x2d66c4f95142a46cULL), + htole64(0x6fa4c33b7a3039c0ULL), + htole64(0xae4faeae1d3ad3d9ULL) + } }, + { { + htole64(0x8886564d3a14d493ULL), + htole64(0x3517454ca23c4af3ULL), + htole64(0x06476983284a0504ULL), + htole64(0x0992abc52d822c37ULL), + htole64(0xd3473e33197a93c9ULL), + htole64(0x399ec6c7e6bf87c9ULL), + htole64(0x51ac86febf240954ULL), + htole64(0xf4c70e16eeaac5ecULL) + } }, + { { + htole64(0xa47f0dd4bf02e71eULL), + htole64(0x36acc2355951a8d9ULL), + htole64(0x69d18d2bd1a5c42fULL), + htole64(0xf4892bcb929b0690ULL), + htole64(0x89b4443b4ddbc49aULL), + htole64(0x4eb7f8719c36de1eULL), + htole64(0x03e7aa020c6e4141ULL), + htole64(0x9b1f5b424d93c9a7ULL) + } }, + { { + htole64(0x7261445183235adbULL), + htole64(0x0e38dc92cb1f2a60ULL), + htole64(0x7b2b8a9aa6079c54ULL), + htole64(0x800a440bdbb2ceb1ULL), + htole64(0x3cd955b7e00d0984ULL), + htole64(0x3a7d3a1b25894224ULL), + htole64(0x944c9ad8ec165fdeULL), + htole64(0x378f5a541631229bULL) + } }, + { { + htole64(0x74b4c7fb98459cedULL), + htole64(0x3698fad1153bb6c3ULL), + htole64(0x7a1e6c303b7652f4ULL), + htole64(0x9fe76702af69334bULL), + htole64(0x1fffe18a1b336103ULL), + htole64(0x8941e71cff8a78dbULL), + htole64(0x382ae548b2e4f3f3ULL), + htole64(0xabbedea680056f52ULL) + } }, + { { + htole64(0x6bcaa4cd81f32d1bULL), + htole64(0xdea2594ac06fd85dULL), + htole64(0xefbacd1d7d476e98ULL), + htole64(0x8a1d71efea48b9caULL), + htole64(0x2001802114846679ULL), + htole64(0xd8fa6bbbebab0761ULL), + htole64(0x3002c6cd635afe94ULL), + htole64(0x7bcd9ed0efc889fbULL) + } }, + { { + htole64(0x48bc924af11bd720ULL), + htole64(0xfaf417d5d9b21b99ULL), + htole64(0xe71da4aa88e12852ULL), + htole64(0x5d80ef9d1891cc86ULL), + htole64(0xf82012d430219f9bULL), + htole64(0xcda43c32bcdf1d77ULL), + htole64(0xd21380b00449b17aULL), + htole64(0x378ee767f11631baULL) + } } +}; + + +static const uint8_t Tau[64] = { + 0, 8, 16, 24, 32, 40, 48, 56, + 1, 9, 17, 25, 33, 41, 49, 57, + 2, 10, 18, 26, 34, 42, 50, 58, + 3, 11, 19, 27, 35, 43, 51, 59, + 4, 12, 20, 28, 36, 44, 52, 60, + 5, 13, 21, 29, 37, 45, 53, 61, + 6, 14, 22, 30, 38, 46, 54, 62, + 7, 15, 23, 31, 39, 47, 55, 63 +}; + +static const uint8_t Pi[256] = { + 252, 238, 221, 17, 207, 110, 49, 22, + 251, 196, 250, 218, 35, 197, 4, 77, + 233, 119, 240, 219, 147, 46, 153, 186, + 23, 54, 241, 187, 20, 205, 95, 193, + 249, 24, 101, 90, 226, 92, 239, 33, + 129, 28, 60, 66, 139, 1, 142, 79, + 5, 132, 2, 174, 227, 106, 143, 160, + 6, 11, 237, 152, 127, 212, 211, 31, + 235, 52, 44, 81, 234, 200, 72, 171, + 242, 42, 104, 162, 253, 58, 206, 204, + 181, 112, 14, 86, 8, 12, 118, 18, + 191, 114, 19, 71, 156, 183, 93, 135, + 21, 161, 150, 41, 16, 123, 154, 199, + 243, 145, 120, 111, 157, 158, 178, 177, + 50, 117, 25, 61, 255, 53, 138, 126, + 109, 84, 198, 128, 195, 189, 13, 87, + 223, 245, 36, 169, 62, 168, 67, 201, + 215, 121, 214, 246, 124, 34, 185, 3, + 224, 15, 236, 222, 122, 148, 176, 188, + 220, 232, 40, 80, 78, 51, 10, 74, + 167, 151, 96, 115, 30, 0, 98, 68, + 26, 184, 56, 130, 100, 159, 38, 65, + 173, 69, 70, 146, 39, 94, 85, 47, + 140, 163, 165, 125, 105, 213, 149, 59, + 7, 88, 179, 64, 134, 172, 29, 247, + 48, 55, 107, 228, 136, 217, 231, 137, + 225, 27, 131, 73, 76, 63, 248, 254, + 141, 83, 170, 144, 202, 216, 133, 97, + 32, 113, 103, 164, 45, 43, 9, 91, + 203, 155, 37, 208, 190, 229, 108, 82, + 89, 166, 116, 210, 230, 244, 180, 192, + 209, 102, 175, 194, 57, 75, 99, 182 +}; + +static const unsigned long long Ax[8][256] = { + { + 0xd01f715b5c7ef8e6ULL, 0x16fa240980778325ULL, 0xa8a42e857ee049c8ULL, + 0x6ac1068fa186465bULL, 0x6e417bd7a2e9320bULL, 0x665c8167a437daabULL, + 0x7666681aa89617f6ULL, 0x4b959163700bdcf5ULL, 0xf14be6b78df36248ULL, + 0xc585bd689a625cffULL, 0x9557d7fca67d82cbULL, 0x89f0b969af6dd366ULL, + 0xb0833d48749f6c35ULL, 0xa1998c23b1ecbc7cULL, 0x8d70c431ac02a736ULL, + 0xd6dfbc2fd0a8b69eULL, 0x37aeb3e551fa198bULL, 0x0b7d128a40b5cf9cULL, + 0x5a8f2008b5780cbcULL, 0xedec882284e333e5ULL, 0xd25fc177d3c7c2ceULL, + 0x5e0f5d50b61778ecULL, 0x1d873683c0c24cb9ULL, 0xad040bcbb45d208cULL, + 0x2f89a0285b853c76ULL, 0x5732fff6791b8d58ULL, 0x3e9311439ef6ec3fULL, + 0xc9183a809fd3c00fULL, 0x83adf3f5260a01eeULL, 0xa6791941f4e8ef10ULL, + 0x103ae97d0ca1cd5dULL, 0x2ce948121dee1b4aULL, 0x39738421dbf2bf53ULL, + 0x093da2a6cf0cf5b4ULL, 0xcd9847d89cbcb45fULL, 0xf9561c078b2d8ae8ULL, + 0x9c6a755a6971777fULL, 0xbc1ebaa0712ef0c5ULL, 0x72e61542abf963a6ULL, + 0x78bb5fde229eb12eULL, 0x14ba94250fceb90dULL, 0x844d6697630e5282ULL, + 0x98ea08026a1e032fULL, 0xf06bbea144217f5cULL, 0xdb6263d11ccb377aULL, + 0x641c314b2b8ee083ULL, 0x320e96ab9b4770cfULL, 0x1ee7deb986a96b85ULL, + 0xe96cf57a878c47b5ULL, 0xfdd6615f8842feb8ULL, 0xc83862965601dd1bULL, + 0x2ea9f83e92572162ULL, 0xf876441142ff97fcULL, 0xeb2c455608357d9dULL, + 0x5612a7e0b0c9904cULL, 0x6c01cbfb2d500823ULL, 0x4548a6a7fa037a2dULL, + 0xabc4c6bf388b6ef4ULL, 0xbade77d4fdf8bebdULL, 0x799b07c8eb4cac3aULL, + 0x0c9d87e805b19cf0ULL, 0xcb588aac106afa27ULL, 0xea0c1d40c1e76089ULL, + 0x2869354a1e816f1aULL, 0xff96d17307fbc490ULL, 0x9f0a9d602f1a5043ULL, + 0x96373fc6e016a5f7ULL, 0x5292dab8b3a6e41cULL, 0x9b8ae0382c752413ULL, + 0x4f15ec3b7364a8a5ULL, 0x3fb349555724f12bULL, 0xc7c50d4415db66d7ULL, + 0x92b7429ee379d1a7ULL, 0xd37f99611a15dfdaULL, 0x231427c05e34a086ULL, + 0xa439a96d7b51d538ULL, 0xb403401077f01865ULL, 0xdda2aea5901d7902ULL, + 0x0a5d4a9c8967d288ULL, 0xc265280adf660f93ULL, 0x8bb0094520d4e94eULL, + 0x2a29856691385532ULL, 0x42a833c5bf072941ULL, 0x73c64d54622b7eb2ULL, + 0x07e095624504536cULL, 0x8a905153e906f45aULL, 0x6f6123c16b3b2f1fULL, + 0xc6e55552dc097bc3ULL, 0x4468feb133d16739ULL, 0xe211e7f0c7398829ULL, + 0xa2f96419f7879b40ULL, 0x19074bdbc3ad38e9ULL, 0xf4ebc3f9474e0b0cULL, + 0x43886bd376d53455ULL, 0xd8028beb5aa01046ULL, 0x51f23282f5cdc320ULL, + 0xe7b1c2be0d84e16dULL, 0x081dfab006dee8a0ULL, 0x3b33340d544b857bULL, + 0x7f5bcabc679ae242ULL, 0x0edd37c48a08a6d8ULL, 0x81ed43d9a9b33bc6ULL, + 0xb1a3655ebd4d7121ULL, 0x69a1eeb5e7ed6167ULL, 0xf6ab73d5c8f73124ULL, + 0x1a67a3e185c61fd5ULL, 0x2dc91004d43c065eULL, 0x0240b02c8fb93a28ULL, + 0x90f7f2b26cc0eb8fULL, 0x3cd3a16f114fd617ULL, 0xaae49ea9f15973e0ULL, + 0x06c0cd748cd64e78ULL, 0xda423bc7d5192a6eULL, 0xc345701c16b41287ULL, + 0x6d2193ede4821537ULL, 0xfcf639494190e3acULL, 0x7c3b228621f1c57eULL, + 0xfb16ac2b0494b0c0ULL, 0xbf7e529a3745d7f9ULL, 0x6881b6a32e3f7c73ULL, + 0xca78d2bad9b8e733ULL, 0xbbfe2fc2342aa3a9ULL, 0x0dbddffecc6381e4ULL, + 0x70a6a56e2440598eULL, 0xe4d12a844befc651ULL, 0x8c509c2765d0ba22ULL, + 0xee8c6018c28814d9ULL, 0x17da7c1f49a59e31ULL, 0x609c4c1328e194d3ULL, + 0xb3e3d57232f44b09ULL, 0x91d7aaa4a512f69bULL, 0x0ffd6fd243dabbccULL, + 0x50d26a943c1fde34ULL, 0x6be15e9968545b4fULL, 0x94778fea6faf9fdfULL, + 0x2b09dd7058ea4826ULL, 0x677cd9716de5c7bfULL, 0x49d5214fffb2e6ddULL, + 0x0360e83a466b273cULL, 0x1fc786af4f7b7691ULL, 0xa0b9d435783ea168ULL, + 0xd49f0c035f118cb6ULL, 0x01205816c9d21d14ULL, 0xac2453dd7d8f3d98ULL, + 0x545217cc3f70aa64ULL, 0x26b4028e9489c9c2ULL, 0xdec2469fd6765e3eULL, + 0x04807d58036f7450ULL, 0xe5f17292823ddb45ULL, 0xf30b569b024a5860ULL, + 0x62dcfc3fa758aefbULL, 0xe84cad6c4e5e5aa1ULL, 0xccb81fce556ea94bULL, + 0x53b282ae7a74f908ULL, 0x1b47fbf74c1402c1ULL, 0x368eebf39828049fULL, + 0x7afbeff2ad278b06ULL, 0xbe5e0a8cfe97caedULL, 0xcfd8f7f413058e77ULL, + 0xf78b2bc301252c30ULL, 0x4d555c17fcdd928dULL, 0x5f2f05467fc565f8ULL, + 0x24f4b2a21b30f3eaULL, 0x860dd6bbecb768aaULL, 0x4c750401350f8f99ULL, + 0x0000000000000000ULL, 0xecccd0344d312ef1ULL, 0xb5231806be220571ULL, + 0xc105c030990d28afULL, 0x653c695de25cfd97ULL, 0x159acc33c61ca419ULL, + 0xb89ec7f872418495ULL, 0xa9847693b73254dcULL, 0x58cf90243ac13694ULL, + 0x59efc832f3132b80ULL, 0x5c4fed7c39ae42c4ULL, 0x828dabe3efd81cfaULL, + 0xd13f294d95ace5f2ULL, 0x7d1b7a90e823d86aULL, 0xb643f03cf849224dULL, + 0x3df3f979d89dcb03ULL, 0x7426d836272f2ddeULL, 0xdfe21e891fa4432aULL, + 0x3a136c1b9d99986fULL, 0xfa36f43dcd46add4ULL, 0xc025982650df35bbULL, + 0x856d3e81aadc4f96ULL, 0xc4a5e57e53b041ebULL, 0x4708168b75ba4005ULL, + 0xaf44bbe73be41aa4ULL, 0x971767d029c4b8e3ULL, 0xb9be9feebb939981ULL, + 0x215497ecd18d9aaeULL, 0x316e7e91dd2c57f3ULL, 0xcef8afe2dad79363ULL, + 0x3853dc371220a247ULL, 0x35ee03c9de4323a3ULL, 0xe6919aa8c456fc79ULL, + 0xe05157dc4880b201ULL, 0x7bdbb7e464f59612ULL, 0x127a59518318f775ULL, + 0x332ecebd52956ddbULL, 0x8f30741d23bb9d1eULL, 0xd922d3fd93720d52ULL, + 0x7746300c61440ae2ULL, 0x25d4eab4d2e2eefeULL, 0x75068020eefd30caULL, + 0x135a01474acaea61ULL, 0x304e268714fe4ae7ULL, 0xa519f17bb283c82cULL, + 0xdc82f6b359cf6416ULL, 0x5baf781e7caa11a8ULL, 0xb2c38d64fb26561dULL, + 0x34ce5bdf17913eb7ULL, 0x5d6fb56af07c5fd0ULL, 0x182713cd0a7f25fdULL, + 0x9e2ac576e6c84d57ULL, 0x9aaab82ee5a73907ULL, 0xa3d93c0f3e558654ULL, + 0x7e7b92aaae48ff56ULL, 0x872d8ead256575beULL, 0x41c8dbfff96c0e7dULL, + 0x99ca5014a3cc1e3bULL, 0x40e883e930be1369ULL, 0x1ca76e95091051adULL, + 0x4e35b42dbab6b5b1ULL, 0x05a0254ecabd6944ULL, 0xe1710fca8152af15ULL, + 0xf22b0e8dcb984574ULL, 0xb763a82a319b3f59ULL, 0x63fca4296e8ab3efULL, + 0x9d4a2d4ca0a36a6bULL, 0xe331bfe60eeb953dULL, 0xd5bf541596c391a2ULL, + 0xf5cb9bef8e9c1618ULL, 0x46284e9dbc685d11ULL, 0x2074cffa185f87baULL, + 0xbd3ee2b6b8fcedd1ULL, 0xae64e3f1f23607b0ULL, 0xfeb68965ce29d984ULL, + 0x55724fdaf6a2b770ULL, 0x29496d5cd753720eULL, 0xa75941573d3af204ULL, + 0x8e102c0bea69800aULL, 0x111ab16bc573d049ULL, 0xd7ffe439197aab8aULL, + 0xefac380e0b5a09cdULL, 0x48f579593660fbc9ULL, 0x22347fd697e6bd92ULL, + 0x61bc1405e13389c7ULL, 0x4ab5c975b9d9c1e1ULL, 0x80cd1bcf606126d2ULL, + 0x7186fd78ed92449aULL, 0x93971a882aabccb3ULL, 0x88d0e17f66bfce72ULL, + 0x27945a985d5bd4d6ULL + }, { + 0xde553f8c05a811c8ULL, 0x1906b59631b4f565ULL, 0x436e70d6b1964ff7ULL, + 0x36d343cb8b1e9d85ULL, 0x843dfacc858aab5aULL, 0xfdfc95c299bfc7f9ULL, + 0x0f634bdea1d51fa2ULL, 0x6d458b3b76efb3cdULL, 0x85c3f77cf8593f80ULL, + 0x3c91315fbe737cb2ULL, 0x2148b03366ace398ULL, 0x18f8b8264c6761bfULL, + 0xc830c1c495c9fb0fULL, 0x981a76102086a0aaULL, 0xaa16012142f35760ULL, + 0x35cc54060c763cf6ULL, 0x42907d66cc45db2dULL, 0x8203d44b965af4bcULL, + 0x3d6f3cefc3a0e868ULL, 0xbc73ff69d292bda7ULL, 0x8722ed0102e20a29ULL, + 0x8f8185e8cd34deb7ULL, 0x9b0561dda7ee01d9ULL, 0x5335a0193227fad6ULL, + 0xc9cecc74e81a6fd5ULL, 0x54f5832e5c2431eaULL, 0x99e47ba05d553470ULL, + 0xf7bee756acd226ceULL, 0x384e05a5571816fdULL, 0xd1367452a47d0e6aULL, + 0xf29fde1c386ad85bULL, 0x320c77316275f7caULL, 0xd0c879e2d9ae9ab0ULL, + 0xdb7406c69110ef5dULL, 0x45505e51a2461011ULL, 0xfc029872e46c5323ULL, + 0xfa3cb6f5f7bc0cc5ULL, 0x031f17cd8768a173ULL, 0xbd8df2d9af41297dULL, + 0x9d3b4f5ab43e5e3fULL, 0x4071671b36feee84ULL, 0x716207e7d3e3b83dULL, + 0x48d20ff2f9283a1aULL, 0x27769eb4757cbc7eULL, 0x5c56ebc793f2e574ULL, + 0xa48b474f9ef5dc18ULL, 0x52cbada94ff46e0cULL, 0x60c7da982d8199c6ULL, + 0x0e9d466edc068b78ULL, 0x4eec2175eaf865fcULL, 0x550b8e9e21f7a530ULL, + 0x6b7ba5bc653fec2bULL, 0x5eb7f1ba6949d0ddULL, 0x57ea94e3db4c9099ULL, + 0xf640eae6d101b214ULL, 0xdd4a284182c0b0bbULL, 0xff1d8fbf6304f250ULL, + 0xb8accb933bf9d7e8ULL, 0xe8867c478eb68c4dULL, 0x3f8e2692391bddc1ULL, + 0xcb2fd60912a15a7cULL, 0xaec935dbab983d2fULL, 0xf55ffd2b56691367ULL, + 0x80e2ce366ce1c115ULL, 0x179bf3f8edb27e1dULL, 0x01fe0db07dd394daULL, + 0xda8a0b76ecc37b87ULL, 0x44ae53e1df9584cbULL, 0xb310b4b77347a205ULL, + 0xdfab323c787b8512ULL, 0x3b511268d070b78eULL, 0x65e6e3d2b9396753ULL, + 0x6864b271e2574d58ULL, 0x259784c98fc789d7ULL, 0x02e11a7dfabb35a9ULL, + 0x8841a6dfa337158bULL, 0x7ade78c39b5dcdd0ULL, 0xb7cf804d9a2cc84aULL, + 0x20b6bd831b7f7742ULL, 0x75bd331d3a88d272ULL, 0x418f6aab4b2d7a5eULL, + 0xd9951cbb6babdaf4ULL, 0xb6318dfde7ff5c90ULL, 0x1f389b112264aa83ULL, + 0x492c024284fbaec0ULL, 0xe33a0363c608f9a0ULL, 0x2688930408af28a4ULL, + 0xc7538a1a341ce4adULL, 0x5da8e677ee2171aeULL, 0x8c9e92254a5c7fc4ULL, + 0x63d8cd55aae938b5ULL, 0x29ebd8daa97a3706ULL, 0x959827b37be88aa1ULL, + 0x1484e4356adadf6eULL, 0xa7945082199d7d6bULL, 0xbf6ce8a455fa1cd4ULL, + 0x9cc542eac9edcae5ULL, 0x79c16f0e1c356ca3ULL, 0x89bfab6fdee48151ULL, + 0xd4174d1830c5f0ffULL, 0x9258048415eb419dULL, 0x6139d72850520d1cULL, + 0x6a85a80c18ec78f1ULL, 0xcd11f88e0171059aULL, 0xcceff53e7ca29140ULL, + 0xd229639f2315af19ULL, 0x90b91ef9ef507434ULL, 0x5977d28d074a1be1ULL, + 0x311360fce51d56b9ULL, 0xc093a92d5a1f2f91ULL, 0x1a19a25bb6dc5416ULL, + 0xeb996b8a09de2d3eULL, 0xfee3820f1ed7668aULL, 0xd7085ad5b7ad518cULL, + 0x7fff41890fe53345ULL, 0xec5948bd67dde602ULL, 0x2fd5f65dbaaa68e0ULL, + 0xa5754affe32648c2ULL, 0xf8ddac880d07396cULL, 0x6fa491468c548664ULL, + 0x0c7c5c1326bdbed1ULL, 0x4a33158f03930fb3ULL, 0x699abfc19f84d982ULL, + 0xe4fa2054a80b329cULL, 0x6707f9af438252faULL, 0x08a368e9cfd6d49eULL, + 0x47b1442c58fd25b8ULL, 0xbbb3dc5ebc91769bULL, 0x1665fe489061eac7ULL, + 0x33f27a811fa66310ULL, 0x93a609346838d547ULL, 0x30ed6d4c98cec263ULL, + 0x1dd9816cd8df9f2aULL, 0x94662a03063b1e7bULL, 0x83fdd9fbeb896066ULL, + 0x7b207573e68e590aULL, 0x5f49fc0a149a4407ULL, 0x343259b671a5a82cULL, + 0xfbc2bb458a6f981fULL, 0xc272b350a0a41a38ULL, 0x3aaf1fd8ada32354ULL, + 0x6cbb868b0b3c2717ULL, 0xa2b569c88d2583feULL, 0xf180c9d1bf027928ULL, + 0xaf37386bd64ba9f5ULL, 0x12bacab2790a8088ULL, 0x4c0d3b0810435055ULL, + 0xb2eeb9070e9436dfULL, 0xc5b29067cea7d104ULL, 0xdcb425f1ff132461ULL, + 0x4f122cc5972bf126ULL, 0xac282fa651230886ULL, 0xe7e537992f6393efULL, + 0xe61b3a2952b00735ULL, 0x709c0a57ae302ce7ULL, 0xe02514ae416058d3ULL, + 0xc44c9dd7b37445deULL, 0x5a68c5408022ba92ULL, 0x1c278cdca50c0bf0ULL, + 0x6e5a9cf6f18712beULL, 0x86dce0b17f319ef3ULL, 0x2d34ec2040115d49ULL, + 0x4bcd183f7e409b69ULL, 0x2815d56ad4a9a3dcULL, 0x24698979f2141d0dULL, + 0x0000000000000000ULL, 0x1ec696a15fb73e59ULL, 0xd86b110b16784e2eULL, + 0x8e7f8858b0e74a6dULL, 0x063e2e8713d05fe6ULL, 0xe2c40ed3bbdb6d7aULL, + 0xb1f1aeca89fc97acULL, 0xe1db191e3cb3cc09ULL, 0x6418ee62c4eaf389ULL, + 0xc6ad87aa49cf7077ULL, 0xd6f65765ca7ec556ULL, 0x9afb6c6dda3d9503ULL, + 0x7ce05644888d9236ULL, 0x8d609f95378feb1eULL, 0x23a9aa4e9c17d631ULL, + 0x6226c0e5d73aac6fULL, 0x56149953a69f0443ULL, 0xeeb852c09d66d3abULL, + 0x2b0ac2a753c102afULL, 0x07c023376e03cb3cULL, 0x2ccae1903dc2c993ULL, + 0xd3d76e2f5ec63bc3ULL, 0x9e2458973356ff4cULL, 0xa66a5d32644ee9b1ULL, + 0x0a427294356de137ULL, 0x783f62be61e6f879ULL, 0x1344c70204d91452ULL, + 0x5b96c8f0fdf12e48ULL, 0xa90916ecc59bf613ULL, 0xbe92e5142829880eULL, + 0x727d102a548b194eULL, 0x1be7afebcb0fc0ccULL, 0x3e702b2244c8491bULL, + 0xd5e940a84d166425ULL, 0x66f9f41f3e51c620ULL, 0xabe80c913f20c3baULL, + 0xf07ec461c2d1edf2ULL, 0xf361d3ac45b94c81ULL, 0x0521394a94b8fe95ULL, + 0xadd622162cf09c5cULL, 0xe97871f7f3651897ULL, 0xf4a1f09b2bba87bdULL, + 0x095d6559b2054044ULL, 0x0bbc7f2448be75edULL, 0x2af4cf172e129675ULL, + 0x157ae98517094bb4ULL, 0x9fda55274e856b96ULL, 0x914713499283e0eeULL, + 0xb952c623462a4332ULL, 0x74433ead475b46a8ULL, 0x8b5eb112245fb4f8ULL, + 0xa34b6478f0f61724ULL, 0x11a5dd7ffe6221fbULL, 0xc16da49d27ccbb4bULL, + 0x76a224d0bde07301ULL, 0x8aa0bca2598c2022ULL, 0x4df336b86d90c48fULL, + 0xea67663a740db9e4ULL, 0xef465f70e0b54771ULL, 0x39b008152acb8227ULL, + 0x7d1e5bf4f55e06ecULL, 0x105bd0cf83b1b521ULL, 0x775c2960c033e7dbULL, + 0x7e014c397236a79fULL, 0x811cc386113255cfULL, 0xeda7450d1a0e72d8ULL, + 0x5889df3d7a998f3bULL, 0x2e2bfbedc779fc3aULL, 0xce0eef438619a4e9ULL, + 0x372d4e7bf6cd095fULL, 0x04df34fae96b6a4fULL, 0xf923a13870d4adb6ULL, + 0xa1aa7e050a4d228dULL, 0xa8f71b5cb84862c9ULL, 0xb52e9a306097fde3ULL, + 0x0d8251a35b6e2a0bULL, 0x2257a7fee1c442ebULL, 0x73831d9a29588d94ULL, + 0x51d4ba64c89ccf7fULL, 0x502ab7d4b54f5ba5ULL, 0x97793dce8153bf08ULL, + 0xe5042de4d5d8a646ULL, 0x9687307efc802bd2ULL, 0xa05473b5779eb657ULL, + 0xb4d097801d446939ULL, 0xcff0e2f3fbca3033ULL, 0xc38cbee0dd778ee2ULL, + 0x464f499c252eb162ULL, 0xcad1dbb96f72cea6ULL, 0xba4dd1eec142e241ULL, + 0xb00fa37af42f0376ULL + }, { + 0xcce4cd3aa968b245ULL, 0x089d5484e80b7fafULL, 0x638246c1b3548304ULL, + 0xd2fe0ec8c2355492ULL, 0xa7fbdf7ff2374eeeULL, 0x4df1600c92337a16ULL, + 0x84e503ea523b12fbULL, 0x0790bbfd53ab0c4aULL, 0x198a780f38f6ea9dULL, + 0x2ab30c8f55ec48cbULL, 0xe0f7fed6b2c49db5ULL, 0xb6ecf3f422cadbdcULL, + 0x409c9a541358df11ULL, 0xd3ce8a56dfde3fe3ULL, 0xc3e9224312c8c1a0ULL, + 0x0d6dfa58816ba507ULL, 0xddf3e1b179952777ULL, 0x04c02a42748bb1d9ULL, + 0x94c2abff9f2decb8ULL, 0x4f91752da8f8acf4ULL, 0x78682befb169bf7bULL, + 0xe1c77a48af2ff6c4ULL, 0x0c5d7ec69c80ce76ULL, 0x4cc1e4928fd81167ULL, + 0xfeed3d24d9997b62ULL, 0x518bb6dfc3a54a23ULL, 0x6dbf2d26151f9b90ULL, + 0xb5bc624b05ea664fULL, 0xe86aaa525acfe21aULL, 0x4801ced0fb53a0beULL, + 0xc91463e6c00868edULL, 0x1027a815cd16fe43ULL, 0xf67069a0319204cdULL, + 0xb04ccc976c8abce7ULL, 0xc0b9b3fc35e87c33ULL, 0xf380c77c58f2de65ULL, + 0x50bb3241de4e2152ULL, 0xdf93f490435ef195ULL, 0xf1e0d25d62390887ULL, + 0xaf668bfb1a3c3141ULL, 0xbc11b251f00a7291ULL, 0x73a5eed47e427d47ULL, + 0x25bee3f6ee4c3b2eULL, 0x43cc0beb34786282ULL, 0xc824e778dde3039cULL, + 0xf97d86d98a327728ULL, 0xf2b043e24519b514ULL, 0xe297ebf7880f4b57ULL, + 0x3a94a49a98fab688ULL, 0x868516cb68f0c419ULL, 0xeffa11af0964ee50ULL, + 0xa4ab4ec0d517f37dULL, 0xa9c6b498547c567aULL, 0x8e18424f80fbbbb6ULL, + 0x0bcdc53bcf2bc23cULL, 0x137739aaea3643d0ULL, 0x2c1333ec1bac2ff0ULL, + 0x8d48d3f0a7db0625ULL, 0x1e1ac3f26b5de6d7ULL, 0xf520f81f16b2b95eULL, + 0x9f0f6ec450062e84ULL, 0x0130849e1deb6b71ULL, 0xd45e31ab8c7533a9ULL, + 0x652279a2fd14e43fULL, 0x3209f01e70f1c927ULL, 0xbe71a770cac1a473ULL, + 0x0e3d6be7a64b1894ULL, 0x7ec8148cff29d840ULL, 0xcb7476c7fac3be0fULL, + 0x72956a4a63a91636ULL, 0x37f95ec21991138fULL, 0x9e3fea5a4ded45f5ULL, + 0x7b38ba50964902e8ULL, 0x222e580bbde73764ULL, 0x61e253e0899f55e6ULL, + 0xfc8d2805e352ad80ULL, 0x35994be3235ac56dULL, 0x09add01af5e014deULL, + 0x5e8659a6780539c6ULL, 0xb17c48097161d796ULL, 0x026015213acbd6e2ULL, + 0xd1ae9f77e515e901ULL, 0xb7dc776a3f21b0adULL, 0xaba6a1b96eb78098ULL, + 0x9bcf4486248d9f5dULL, 0x582666c536455efdULL, 0xfdbdac9bfeb9c6f1ULL, + 0xc47999be4163cdeaULL, 0x765540081722a7efULL, 0x3e548ed8ec710751ULL, + 0x3d041f67cb51bac2ULL, 0x7958af71ac82d40aULL, 0x36c9da5c047a78feULL, + 0xed9a048e33af38b2ULL, 0x26ee7249c96c86bdULL, 0x900281bdeba65d61ULL, + 0x11172c8bd0fd9532ULL, 0xea0abf73600434f8ULL, 0x42fc8f75299309f3ULL, + 0x34a9cf7d3eb1ae1cULL, 0x2b838811480723baULL, 0x5ce64c8742ceef24ULL, + 0x1adae9b01fd6570eULL, 0x3c349bf9d6bad1b3ULL, 0x82453c891c7b75c0ULL, + 0x97923a40b80d512bULL, 0x4a61dbf1c198765cULL, 0xb48ce6d518010d3eULL, + 0xcfb45c858e480fd6ULL, 0xd933cbf30d1e96aeULL, 0xd70ea014ab558e3aULL, + 0xc189376228031742ULL, 0x9262949cd16d8b83ULL, 0xeb3a3bed7def5f89ULL, + 0x49314a4ee6b8cbcfULL, 0xdcc3652f647e4c06ULL, 0xda635a4c2a3e2b3dULL, + 0x470c21a940f3d35bULL, 0x315961a157d174b4ULL, 0x6672e81dda3459acULL, + 0x5b76f77a1165e36eULL, 0x445cb01667d36ec8ULL, 0xc5491d205c88a69bULL, + 0x456c34887a3805b9ULL, 0xffddb9bac4721013ULL, 0x99af51a71e4649bfULL, + 0xa15be01cbc7729d5ULL, 0x52db2760e485f7b0ULL, 0x8c78576eba306d54ULL, + 0xae560f6507d75a30ULL, 0x95f22f6182c687c9ULL, 0x71c5fbf54489aba5ULL, + 0xca44f259e728d57eULL, 0x88b87d2ccebbdc8dULL, 0xbab18d32be4a15aaULL, + 0x8be8ec93e99b611eULL, 0x17b713e89ebdf209ULL, 0xb31c5d284baa0174ULL, + 0xeeca9531148f8521ULL, 0xb8d198138481c348ULL, 0x8988f9b2d350b7fcULL, + 0xb9e11c8d996aa839ULL, 0x5a4673e40c8e881fULL, 0x1687977683569978ULL, + 0xbf4123eed72acf02ULL, 0x4ea1f1b3b513c785ULL, 0xe767452be16f91ffULL, + 0x7505d1b730021a7cULL, 0xa59bca5ec8fc980cULL, 0xad069eda20f7e7a3ULL, + 0x38f4b1bba231606aULL, 0x60d2d77e94743e97ULL, 0x9affc0183966f42cULL, + 0x248e6768f3a7505fULL, 0xcdd449a4b483d934ULL, 0x87b59255751baf68ULL, + 0x1bea6d2e023d3c7fULL, 0x6b1f12455b5ffcabULL, 0x743555292de9710dULL, + 0xd8034f6d10f5fddfULL, 0xc6198c9f7ba81b08ULL, 0xbb8109aca3a17edbULL, + 0xfa2d1766ad12cabbULL, 0xc729080166437079ULL, 0x9c5fff7b77269317ULL, + 0x0000000000000000ULL, 0x15d706c9a47624ebULL, 0x6fdf38072fd44d72ULL, + 0x5fb6dd3865ee52b7ULL, 0xa33bf53d86bcff37ULL, 0xe657c1b5fc84fa8eULL, + 0xaa962527735cebe9ULL, 0x39c43525bfda0b1bULL, 0x204e4d2a872ce186ULL, + 0x7a083ece8ba26999ULL, 0x554b9c9db72efbfaULL, 0xb22cd9b656416a05ULL, + 0x96a2bedea5e63a5aULL, 0x802529a826b0a322ULL, 0x8115ad363b5bc853ULL, + 0x8375b81701901eb1ULL, 0x3069e53f4a3a1fc5ULL, 0xbd2136cfede119e0ULL, + 0x18bafc91251d81ecULL, 0x1d4a524d4c7d5b44ULL, 0x05f0aedc6960daa8ULL, + 0x29e39d3072ccf558ULL, 0x70f57f6b5962c0d4ULL, 0x989fd53903ad22ceULL, + 0xf84d024797d91c59ULL, 0x547b1803aac5908bULL, 0xf0d056c37fd263f6ULL, + 0xd56eb535919e58d8ULL, 0x1c7ad6d351963035ULL, 0x2e7326cd2167f912ULL, + 0xac361a443d1c8cd2ULL, 0x697f076461942a49ULL, 0x4b515f6fdc731d2dULL, + 0x8ad8680df4700a6fULL, 0x41ac1eca0eb3b460ULL, 0x7d988533d80965d3ULL, + 0xa8f6300649973d0bULL, 0x7765c4960ac9cc9eULL, 0x7ca801adc5e20ea2ULL, + 0xdea3700e5eb59ae4ULL, 0xa06b6482a19c42a4ULL, 0x6a2f96db46b497daULL, + 0x27def6d7d487edccULL, 0x463ca5375d18b82aULL, 0xa6cb5be1efdc259fULL, + 0x53eba3fef96e9cc1ULL, 0xce84d81b93a364a7ULL, 0xf4107c810b59d22fULL, + 0x333974806d1aa256ULL, 0x0f0def79bba073e5ULL, 0x231edc95a00c5c15ULL, + 0xe437d494c64f2c6cULL, 0x91320523f64d3610ULL, 0x67426c83c7df32ddULL, + 0x6eefbc99323f2603ULL, 0x9d6f7be56acdf866ULL, 0x5916e25b2bae358cULL, + 0x7ff89012e2c2b331ULL, 0x035091bf2720bd93ULL, 0x561b0d22900e4669ULL, + 0x28d319ae6f279e29ULL, 0x2f43a2533c8c9263ULL, 0xd09e1be9f8fe8270ULL, + 0xf740ed3e2c796fbcULL, 0xdb53ded237d5404cULL, 0x62b2c25faebfe875ULL, + 0x0afd41a5d2c0a94dULL, 0x6412fd3ce0ff8f4eULL, 0xe3a76f6995e42026ULL, + 0x6c8fa9b808f4f0e1ULL, 0xc2d9a6dd0f23aad1ULL, 0x8f28c6d19d10d0c7ULL, + 0x85d587744fd0798aULL, 0xa20b71a39b579446ULL, 0x684f83fa7c7f4138ULL, + 0xe507500adba4471dULL, 0x3f640a46f19a6c20ULL, 0x1247bd34f7dd28a1ULL, + 0x2d23b77206474481ULL, 0x93521002cc86e0f2ULL, 0x572b89bc8de52d18ULL, + 0xfb1d93f8b0f9a1caULL, 0xe95a2ecc4724896bULL, 0x3ba420048511ddf9ULL, + 0xd63e248ab6bee54bULL, 0x5dd6c8195f258455ULL, 0x06a03f634e40673bULL, + 0x1f2a476c76b68da6ULL, 0x217ec9b49ac78af7ULL, 0xecaa80102e4453c3ULL, + 0x14e78257b99d4f9aULL + }, { + 0x20329b2cc87bba05ULL, 0x4f5eb6f86546a531ULL, 0xd4f44775f751b6b1ULL, + 0x8266a47b850dfa8bULL, 0xbb986aa15a6ca985ULL, 0xc979eb08f9ae0f99ULL, + 0x2da6f447a2375ea1ULL, 0x1e74275dcd7d8576ULL, 0xbc20180a800bc5f8ULL, + 0xb4a2f701b2dc65beULL, 0xe726946f981b6d66ULL, 0x48e6c453bf21c94cULL, + 0x42cad9930f0a4195ULL, 0xefa47b64aacccd20ULL, 0x71180a8960409a42ULL, + 0x8bb3329bf6a44e0cULL, 0xd34c35de2d36daccULL, 0xa92f5b7cbc23dc96ULL, + 0xb31a85aa68bb09c3ULL, 0x13e04836a73161d2ULL, 0xb24dfc4129c51d02ULL, + 0x8ae44b70b7da5acdULL, 0xe671ed84d96579a7ULL, 0xa4bb3417d66f3832ULL, + 0x4572ab38d56d2de8ULL, 0xb1b47761ea47215cULL, 0xe81c09cf70aba15dULL, + 0xffbdb872ce7f90acULL, 0xa8782297fd5dc857ULL, 0x0d946f6b6a4ce4a4ULL, + 0xe4df1f4f5b995138ULL, 0x9ebc71edca8c5762ULL, 0x0a2c1dc0b02b88d9ULL, + 0x3b503c115d9d7b91ULL, 0xc64376a8111ec3a2ULL, 0xcec199a323c963e4ULL, + 0xdc76a87ec58616f7ULL, 0x09d596e073a9b487ULL, 0x14583a9d7d560dafULL, + 0xf4c6dc593f2a0cb4ULL, 0xdd21d19584f80236ULL, 0x4a4836983ddde1d3ULL, + 0xe58866a41ae745f9ULL, 0xf591a5b27e541875ULL, 0x891dc05074586693ULL, + 0x5b068c651810a89eULL, 0xa30346bc0c08544fULL, 0x3dbf3751c684032dULL, + 0x2a1e86ec785032dcULL, 0xf73f5779fca830eaULL, 0xb60c05ca30204d21ULL, + 0x0cc316802b32f065ULL, 0x8770241bdd96be69ULL, 0xb861e18199ee95dbULL, + 0xf805cad91418fcd1ULL, 0x29e70dccbbd20e82ULL, 0xc7140f435060d763ULL, + 0x0f3a9da0e8b0cc3bULL, 0xa2543f574d76408eULL, 0xbd7761e1c175d139ULL, + 0x4b1f4f737ca3f512ULL, 0x6dc2df1f2fc137abULL, 0xf1d05c3967b14856ULL, + 0xa742bf3715ed046cULL, 0x654030141d1697edULL, 0x07b872abda676c7dULL, + 0x3ce84eba87fa17ecULL, 0xc1fb0403cb79afdfULL, 0x3e46bc7105063f73ULL, + 0x278ae987121cd678ULL, 0xa1adb4778ef47cd0ULL, 0x26dd906c5362c2b9ULL, + 0x05168060589b44e2ULL, 0xfbfc41f9d79ac08fULL, 0x0e6de44ba9ced8faULL, + 0x9feb08068bf243a3ULL, 0x7b341749d06b129bULL, 0x229c69e74a87929aULL, + 0xe09ee6c4427c011bULL, 0x5692e30e725c4c3aULL, 0xda99a33e5e9f6e4bULL, + 0x353dd85af453a36bULL, 0x25241b4c90e0fee7ULL, 0x5de987258309d022ULL, + 0xe230140fc0802984ULL, 0x93281e86a0c0b3c6ULL, 0xf229d719a4337408ULL, + 0x6f6c2dd4ad3d1f34ULL, 0x8ea5b2fbae3f0aeeULL, 0x8331dd90c473ee4aULL, + 0x346aa1b1b52db7aaULL, 0xdf8f235e06042aa9ULL, 0xcc6f6b68a1354b7bULL, + 0x6c95a6f46ebf236aULL, 0x52d31a856bb91c19ULL, 0x1a35ded6d498d555ULL, + 0xf37eaef2e54d60c9ULL, 0x72e181a9a3c2a61cULL, 0x98537aad51952fdeULL, + 0x16f6c856ffaa2530ULL, 0xd960281e9d1d5215ULL, 0x3a0745fa1ce36f50ULL, + 0x0b7b642bf1559c18ULL, 0x59a87eae9aec8001ULL, 0x5e100c05408bec7cULL, + 0x0441f98b19e55023ULL, 0xd70dcc5534d38aefULL, 0x927f676de1bea707ULL, + 0x9769e70db925e3e5ULL, 0x7a636ea29115065aULL, 0x468b201816ef11b6ULL, + 0xab81a9b73edff409ULL, 0xc0ac7de88a07bb1eULL, 0x1f235eb68c0391b7ULL, + 0x6056b074458dd30fULL, 0xbe8eeac102f7ed67ULL, 0xcd381283e04b5fbaULL, + 0x5cbefecec277c4e3ULL, 0xd21b4c356c48ce0dULL, 0x1019c31664b35d8cULL, + 0x247362a7d19eea26ULL, 0xebe582efb3299d03ULL, 0x02aef2cb82fc289fULL, + 0x86275df09ce8aaa8ULL, 0x28b07427faac1a43ULL, 0x38a9b7319e1f47cfULL, + 0xc82e92e3b8d01b58ULL, 0x06ef0b409b1978bcULL, 0x62f842bfc771fb90ULL, + 0x9904034610eb3b1fULL, 0xded85ab5477a3e68ULL, 0x90d195a663428f98ULL, + 0x5384636e2ac708d8ULL, 0xcbd719c37b522706ULL, 0xae9729d76644b0ebULL, + 0x7c8c65e20a0c7ee6ULL, 0x80c856b007f1d214ULL, 0x8c0b40302cc32271ULL, + 0xdbcedad51fe17a8aULL, 0x740e8ae938dbdea0ULL, 0xa615c6dc549310adULL, + 0x19cc55f6171ae90bULL, 0x49b1bdb8fe5fdd8dULL, 0xed0a89af2830e5bfULL, + 0x6a7aadb4f5a65bd6ULL, 0x7e22972988f05679ULL, 0xf952b3325566e810ULL, + 0x39fecedadf61530eULL, 0x6101c99f04f3c7ceULL, 0x2e5f7f6761b562ffULL, + 0xf08725d226cf5c97ULL, 0x63af3b54860fef51ULL, 0x8ff2cb10ef411e2fULL, + 0x884ab9bb35267252ULL, 0x4df04433e7ba8daeULL, 0x9afd8866d3690741ULL, + 0x66b9bb34de94abb3ULL, 0x9baaf18d92171380ULL, 0x543c11c5f0a064a5ULL, + 0x17a1b1bdbed431f1ULL, 0xb5f58eeaf3a2717fULL, 0xc355f6c849858740ULL, + 0xec5df044694ef17eULL, 0xd83751f5dc6346d4ULL, 0xfc4433520dfdacf2ULL, + 0x0000000000000000ULL, 0x5a51f58e596ebc5fULL, 0x3285aaf12e34cf16ULL, + 0x8d5c39db6dbd36b0ULL, 0x12b731dde64f7513ULL, 0x94906c2d7aa7dfbbULL, + 0x302b583aacc8e789ULL, 0x9d45facd090e6b3cULL, 0x2165e2c78905aec4ULL, + 0x68d45f7f775a7349ULL, 0x189b2c1d5664fdcaULL, 0xe1c99f2f030215daULL, + 0x6983269436246788ULL, 0x8489af3b1e148237ULL, 0xe94b702431d5b59cULL, + 0x33d2d31a6f4adbd7ULL, 0xbfd9932a4389f9a6ULL, 0xb0e30e8aab39359dULL, + 0xd1e2c715afcaf253ULL, 0x150f43763c28196eULL, 0xc4ed846393e2eb3dULL, + 0x03f98b20c3823c5eULL, 0xfd134ab94c83b833ULL, 0x556b682eb1de7064ULL, + 0x36c4537a37d19f35ULL, 0x7559f30279a5ca61ULL, 0x799ae58252973a04ULL, + 0x9c12832648707ffdULL, 0x78cd9c6913e92ec5ULL, 0x1d8dac7d0effb928ULL, + 0x439da0784e745554ULL, 0x413352b3cc887dcbULL, 0xbacf134a1b12bd44ULL, + 0x114ebafd25cd494dULL, 0x2f08068c20cb763eULL, 0x76a07822ba27f63fULL, + 0xeab2fb04f25789c2ULL, 0xe3676de481fe3d45ULL, 0x1b62a73d95e6c194ULL, + 0x641749ff5c68832cULL, 0xa5ec4dfc97112cf3ULL, 0xf6682e92bdd6242bULL, + 0x3f11c59a44782bb2ULL, 0x317c21d1edb6f348ULL, 0xd65ab5be75ad9e2eULL, + 0x6b2dd45fb4d84f17ULL, 0xfaab381296e4d44eULL, 0xd0b5befeeeb4e692ULL, + 0x0882ef0b32d7a046ULL, 0x512a91a5a83b2047ULL, 0x963e9ee6f85bf724ULL, + 0x4e09cf132438b1f0ULL, 0x77f701c9fb59e2feULL, 0x7ddb1c094b726a27ULL, + 0x5f4775ee01f5f8bdULL, 0x9186ec4d223c9b59ULL, 0xfeeac1998f01846dULL, + 0xac39db1ce4b89874ULL, 0xb75b7c21715e59e0ULL, 0xafc0503c273aa42aULL, + 0x6e3b543fec430bf5ULL, 0x704f7362213e8e83ULL, 0x58ff0745db9294c0ULL, + 0x67eec2df9feabf72ULL, 0xa0facd9ccf8a6811ULL, 0xb936986ad890811aULL, + 0x95c715c63bd9cb7aULL, 0xca8060283a2c33c7ULL, 0x507de84ee9453486ULL, + 0x85ded6d05f6a96f6ULL, 0x1cdad5964f81ade9ULL, 0xd5a33e9eb62fa270ULL, + 0x40642b588df6690aULL, 0x7f75eec2c98e42b8ULL, 0x2cf18dace3494a60ULL, + 0x23cb100c0bf9865bULL, 0xeef3028febb2d9e1ULL, 0x4425d2d394133929ULL, + 0xaad6d05c7fa1e0c8ULL, 0xad6ea2f7a5c68cb5ULL, 0xc2028f2308fb9381ULL, + 0x819f2f5b468fc6d5ULL, 0xc5bafd88d29cfffcULL, 0x47dc59f357910577ULL, + 0x2b49ff07392e261dULL, 0x57c59ae5332258fbULL, 0x73b6f842e2bcb2ddULL, + 0xcf96e04862b77725ULL, 0x4ca73dd8a6c4996fULL, 0x015779eb417e14c1ULL, + 0x37932a9176af8bf4ULL + }, { + 0x190a2c9b249df23eULL, 0x2f62f8b62263e1e9ULL, 0x7a7f754740993655ULL, + 0x330b7ba4d5564d9fULL, 0x4c17a16a46672582ULL, 0xb22f08eb7d05f5b8ULL, + 0x535f47f40bc148ccULL, 0x3aec5d27d4883037ULL, 0x10ed0a1825438f96ULL, + 0x516101f72c233d17ULL, 0x13cc6f949fd04eaeULL, 0x739853c441474bfdULL, + 0x653793d90d3f5b1bULL, 0x5240647b96b0fc2fULL, 0x0c84890ad27623e0ULL, + 0xd7189b32703aaea3ULL, 0x2685de3523bd9c41ULL, 0x99317c5b11bffefaULL, + 0x0d9baa854f079703ULL, 0x70b93648fbd48ac5ULL, 0xa80441fce30bc6beULL, + 0x7287704bdc36ff1eULL, 0xb65384ed33dc1f13ULL, 0xd36417343ee34408ULL, + 0x39cd38ab6e1bf10fULL, 0x5ab861770a1f3564ULL, 0x0ebacf09f594563bULL, + 0xd04572b884708530ULL, 0x3cae9722bdb3af47ULL, 0x4a556b6f2f5cbaf2ULL, + 0xe1704f1f76c4bd74ULL, 0x5ec4ed7144c6dfcfULL, 0x16afc01d4c7810e6ULL, + 0x283f113cd629ca7aULL, 0xaf59a8761741ed2dULL, 0xeed5a3991e215facULL, + 0x3bf37ea849f984d4ULL, 0xe413e096a56ce33cULL, 0x2c439d3a98f020d1ULL, + 0x637559dc6404c46bULL, 0x9e6c95d1e5f5d569ULL, 0x24bb9836045fe99aULL, + 0x44efa466dac8ecc9ULL, 0xc6eab2a5c80895d6ULL, 0x803b50c035220cc4ULL, + 0x0321658cba93c138ULL, 0x8f9ebc465dc7ee1cULL, 0xd15a5137190131d3ULL, + 0x0fa5ec8668e5e2d8ULL, 0x91c979578d1037b1ULL, 0x0642ca05693b9f70ULL, + 0xefca80168350eb4fULL, 0x38d21b24f36a45ecULL, 0xbeab81e1af73d658ULL, + 0x8cbfd9cae7542f24ULL, 0xfd19cc0d81f11102ULL, 0x0ac6430fbb4dbc90ULL, + 0x1d76a09d6a441895ULL, 0x2a01573ff1cbbfa1ULL, 0xb572e161894fde2bULL, + 0x8124734fa853b827ULL, 0x614b1fdf43e6b1b0ULL, 0x68ac395c4238cc18ULL, + 0x21d837bfd7f7b7d2ULL, 0x20c714304a860331ULL, 0x5cfaab726324aa14ULL, + 0x74c5ba4eb50d606eULL, 0xf3a3030474654739ULL, 0x23e671bcf015c209ULL, + 0x45f087e947b9582aULL, 0xd8bd77b418df4c7bULL, 0xe06f6c90ebb50997ULL, + 0x0bd96080263c0873ULL, 0x7e03f9410e40dcfeULL, 0xb8e94be4c6484928ULL, + 0xfb5b0608e8ca8e72ULL, 0x1a2b49179e0e3306ULL, 0x4e29e76961855059ULL, + 0x4f36c4e6fcf4e4baULL, 0x49740ee395cf7bcaULL, 0xc2963ea386d17f7dULL, + 0x90d65ad810618352ULL, 0x12d34c1b02a1fa4dULL, 0xfa44258775bb3a91ULL, + 0x18150f14b9ec46ddULL, 0x1491861e6b9a653dULL, 0x9a1019d7ab2c3fc2ULL, + 0x3668d42d06fe13d7ULL, 0xdcc1fbb25606a6d0ULL, 0x969490dd795a1c22ULL, + 0x3549b1a1bc6dd2efULL, 0xc94f5e23a0ed770eULL, 0xb9f6686b5b39fdcbULL, + 0xc4d4f4a6efeae00dULL, 0xe732851a1fff2204ULL, 0x94aad6de5eb869f9ULL, + 0x3f8ff2ae07206e7fULL, 0xfe38a9813b62d03aULL, 0xa7a1ad7a8bee2466ULL, + 0x7b6056c8dde882b6ULL, 0x302a1e286fc58ca7ULL, 0x8da0fa457a259bc7ULL, + 0xb3302b64e074415bULL, 0x5402ae7eff8b635fULL, 0x08f8050c9cafc94bULL, + 0xae468bf98a3059ceULL, 0x88c355cca98dc58fULL, 0xb10e6d67c7963480ULL, + 0xbad70de7e1aa3cf3ULL, 0xbfb4a26e320262bbULL, 0xcb711820870f02d5ULL, + 0xce12b7a954a75c9dULL, 0x563ce87dd8691684ULL, 0x9f73b65e7884618aULL, + 0x2b1e74b06cba0b42ULL, 0x47cec1ea605b2df1ULL, 0x1c698312f735ac76ULL, + 0x5fdbcefed9b76b2cULL, 0x831a354c8fb1cdfcULL, 0x820516c312c0791fULL, + 0xb74ca762aeadabf0ULL, 0xfc06ef821c80a5e1ULL, 0x5723cbf24518a267ULL, + 0x9d4df05d5f661451ULL, 0x588627742dfd40bfULL, 0xda8331b73f3d39a0ULL, + 0x17b0e392d109a405ULL, 0xf965400bcf28fba9ULL, 0x7c3dbf4229a2a925ULL, + 0x023e460327e275dbULL, 0x6cd0b55a0ce126b3ULL, 0xe62da695828e96e7ULL, + 0x42ad6e63b3f373b9ULL, 0xe50cc319381d57dfULL, 0xc5cbd729729b54eeULL, + 0x46d1e265fd2a9912ULL, 0x6428b056904eeff8ULL, 0x8be23040131e04b7ULL, + 0x6709d5da2add2ec0ULL, 0x075de98af44a2b93ULL, 0x8447dcc67bfbe66fULL, + 0x6616f655b7ac9a23ULL, 0xd607b8bded4b1a40ULL, 0x0563af89d3a85e48ULL, + 0x3db1b4ad20c21ba4ULL, 0x11f22997b8323b75ULL, 0x292032b34b587e99ULL, + 0x7f1cdace9331681dULL, 0x8e819fc9c0b65affULL, 0xa1e3677fe2d5bb16ULL, + 0xcd33d225ee349da5ULL, 0xd9a2543b85aef898ULL, 0x795e10cbfa0af76dULL, + 0x25a4bbb9992e5d79ULL, 0x78413344677b438eULL, 0xf0826688cef68601ULL, + 0xd27b34bba392f0ebULL, 0x551d8df162fad7bcULL, 0x1e57c511d0d7d9adULL, + 0xdeffbdb171e4d30bULL, 0xf4feea8e802f6caaULL, 0xa480c8f6317de55eULL, + 0xa0fc44f07fa40ff5ULL, 0x95b5f551c3c9dd1aULL, 0x22f952336d6476eaULL, + 0x0000000000000000ULL, 0xa6be8ef5169f9085ULL, 0xcc2cf1aa73452946ULL, + 0x2e7ddb39bf12550aULL, 0xd526dd3157d8db78ULL, 0x486b2d6c08becf29ULL, + 0x9b0f3a58365d8b21ULL, 0xac78cdfaadd22c15ULL, 0xbc95c7e28891a383ULL, + 0x6a927f5f65dab9c3ULL, 0xc3891d2c1ba0cb9eULL, 0xeaa92f9f50f8b507ULL, + 0xcf0d9426c9d6e87eULL, 0xca6e3baf1a7eb636ULL, 0xab25247059980786ULL, + 0x69b31ad3df4978fbULL, 0xe2512a93cc577c4cULL, 0xff278a0ea61364d9ULL, + 0x71a615c766a53e26ULL, 0x89dc764334fc716cULL, 0xf87a638452594f4aULL, + 0xf2bc208be914f3daULL, 0x8766b94ac1682757ULL, 0xbbc82e687cdb8810ULL, + 0x626a7a53f9757088ULL, 0xa2c202f358467a2eULL, 0x4d0882e5db169161ULL, + 0x09e7268301de7da8ULL, 0xe897699c771ac0dcULL, 0xc8507dac3d9cc3edULL, + 0xc0a878a0a1330aa6ULL, 0x978bb352e42ba8c1ULL, 0xe9884a13ea6b743fULL, + 0x279afdbabecc28a2ULL, 0x047c8c064ed9eaabULL, 0x507e2278b15289f4ULL, + 0x599904fbb08cf45cULL, 0xbd8ae46d15e01760ULL, 0x31353da7f2b43844ULL, + 0x8558ff49e68a528cULL, 0x76fbfc4d92ef15b5ULL, 0x3456922e211c660cULL, + 0x86799ac55c1993b4ULL, 0x3e90d1219a51da9cULL, 0x2d5cbeb505819432ULL, + 0x982e5fd48cce4a19ULL, 0xdb9c1238a24c8d43ULL, 0xd439febecaa96f9bULL, + 0x418c0bef0960b281ULL, 0x158ea591f6ebd1deULL, 0x1f48e69e4da66d4eULL, + 0x8afd13cf8e6fb054ULL, 0xf5e1c9011d5ed849ULL, 0xe34e091c5126c8afULL, + 0xad67ee7530a398f6ULL, 0x43b24dec2e82c75aULL, 0x75da99c1287cd48dULL, + 0x92e81cdb3783f689ULL, 0xa3dd217cc537cecdULL, 0x60543c50de970553ULL, + 0x93f73f54aaf2426aULL, 0xa91b62737e7a725dULL, 0xf19d4507538732e2ULL, + 0x77e4dfc20f9ea156ULL, 0x7d229ccdb4d31dc6ULL, 0x1b346a98037f87e5ULL, + 0xedf4c615a4b29e94ULL, 0x4093286094110662ULL, 0xb0114ee85ae78063ULL, + 0x6ff1d0d6b672e78bULL, 0x6dcf96d591909250ULL, 0xdfe09e3eec9567e8ULL, + 0x3214582b4827f97cULL, 0xb46dc2ee143e6ac8ULL, 0xf6c0ac8da7cd1971ULL, + 0xebb60c10cd8901e4ULL, 0xf7df8f023abcad92ULL, 0x9c52d3d2c217a0b2ULL, + 0x6b8d5cd0f8ab0d20ULL, 0x3777f7a29b8fa734ULL, 0x011f238f9d71b4e3ULL, + 0xc1b75b2f3c42be45ULL, 0x5de588fdfe551ef7ULL, 0x6eeef3592b035368ULL, + 0xaa3a07ffc4e9b365ULL, 0xecebe59a39c32a77ULL, 0x5ba742f8976e8187ULL, + 0x4b4a48e0b22d0e11ULL, 0xddded83dcb771233ULL, 0xa59feb79ac0c51bdULL, + 0xc7f5912a55792135ULL + }, { + 0x6d6ae04668a9b08aULL, 0x3ab3f04b0be8c743ULL, 0xe51e166b54b3c908ULL, + 0xbe90a9eb35c2f139ULL, 0xb2c7066637f2bec1ULL, 0xaa6945613392202cULL, + 0x9a28c36f3b5201ebULL, 0xddce5a93ab536994ULL, 0x0e34133ef6382827ULL, + 0x52a02ba1ec55048bULL, 0xa2f88f97c4b2a177ULL, 0x8640e513ca2251a5ULL, + 0xcdf1d36258137622ULL, 0xfe6cb708dedf8ddbULL, 0x8a174a9ec8121e5dULL, + 0x679896036b81560eULL, 0x59ed033395795feeULL, 0x1dd778ab8b74edafULL, + 0xee533ef92d9f926dULL, 0x2a8c79baf8a8d8f5ULL, 0x6bcf398e69b119f6ULL, + 0xe20491742fafdd95ULL, 0x276488e0809c2aecULL, 0xea955b82d88f5cceULL, + 0x7102c63a99d9e0c4ULL, 0xf9763017a5c39946ULL, 0x429fa2501f151b3dULL, + 0x4659c72bea05d59eULL, 0x984b7fdccf5a6634ULL, 0xf742232953fbb161ULL, + 0x3041860e08c021c7ULL, 0x747bfd9616cd9386ULL, 0x4bb1367192312787ULL, + 0x1b72a1638a6c44d3ULL, 0x4a0e68a6e8359a66ULL, 0x169a5039f258b6caULL, + 0xb98a2ef44edee5a4ULL, 0xd9083fe85e43a737ULL, 0x967f6ce239624e13ULL, + 0x8874f62d3c1a7982ULL, 0x3c1629830af06e3fULL, 0x9165ebfd427e5a8eULL, + 0xb5dd81794ceeaa5cULL, 0x0de8f15a7834f219ULL, 0x70bd98ede3dd5d25ULL, + 0xaccc9ca9328a8950ULL, 0x56664eda1945ca28ULL, 0x221db34c0f8859aeULL, + 0x26dbd637fa98970dULL, 0x1acdffb4f068f932ULL, 0x4585254f64090fa0ULL, + 0x72de245e17d53afaULL, 0x1546b25d7c546cf4ULL, 0x207e0ffffb803e71ULL, + 0xfaaad2732bcf4378ULL, 0xb462dfae36ea17bdULL, 0xcf926fd1ac1b11fdULL, + 0xe0672dc7dba7ba4aULL, 0xd3fa49ad5d6b41b3ULL, 0x8ba81449b216a3bcULL, + 0x14f9ec8a0650d115ULL, 0x40fc1ee3eb1d7ce2ULL, 0x23a2ed9b758ce44fULL, + 0x782c521b14fddc7eULL, 0x1c68267cf170504eULL, 0xbcf31558c1ca96e6ULL, + 0xa781b43b4ba6d235ULL, 0xf6fd7dfe29ff0c80ULL, 0xb0a4bad5c3fad91eULL, + 0xd199f51ea963266cULL, 0x414340349119c103ULL, 0x5405f269ed4dadf7ULL, + 0xabd61bb649969dcdULL, 0x6813dbeae7bdc3c8ULL, 0x65fb2ab09f8931d1ULL, + 0xf1e7fae152e3181dULL, 0xc1a67cef5a2339daULL, 0x7a4feea8e0f5bba1ULL, + 0x1e0b9acf05783791ULL, 0x5b8ebf8061713831ULL, 0x80e53cdbcb3af8d9ULL, + 0x7e898bd315e57502ULL, 0xc6bcfbf0213f2d47ULL, 0x95a38e86b76e942dULL, + 0x092e94218d243cbaULL, 0x8339debf453622e7ULL, 0xb11be402b9fe64ffULL, + 0x57d9100d634177c9ULL, 0xcc4e8db52217cbc3ULL, 0x3b0cae9c71ec7aa2ULL, + 0xfb158ca451cbfe99ULL, 0x2b33276d82ac6514ULL, 0x01bf5ed77a04bde1ULL, + 0xc5601994af33f779ULL, 0x75c4a3416cc92e67ULL, 0xf3844652a6eb7fc2ULL, + 0x3487e375fdd0ef64ULL, 0x18ae430704609eedULL, 0x4d14efb993298efbULL, + 0x815a620cb13e4538ULL, 0x125c354207487869ULL, 0x9eeea614ce42cf48ULL, + 0xce2d3106d61fac1cULL, 0xbbe99247bad6827bULL, 0x071a871f7b1c149dULL, + 0x2e4a1cc10db81656ULL, 0x77a71ff298c149b8ULL, 0x06a5d9c80118a97cULL, + 0xad73c27e488e34b1ULL, 0x443a7b981e0db241ULL, 0xe3bbcfa355ab6074ULL, + 0x0af276450328e684ULL, 0x73617a896dd1871bULL, 0x58525de4ef7de20fULL, + 0xb7be3dcab8e6cd83ULL, 0x19111dd07e64230cULL, 0x842359a03e2a367aULL, + 0x103f89f1f3401fb6ULL, 0xdc710444d157d475ULL, 0xb835702334da5845ULL, + 0x4320fc876511a6dcULL, 0xd026abc9d3679b8dULL, 0x17250eee885c0b2bULL, + 0x90dab52a387ae76fULL, 0x31fed8d972c49c26ULL, 0x89cba8fa461ec463ULL, + 0x2ff5421677bcabb7ULL, 0x396f122f85e41d7dULL, 0xa09b332430bac6a8ULL, + 0xc888e8ced7070560ULL, 0xaeaf201ac682ee8fULL, 0x1180d7268944a257ULL, + 0xf058a43628e7a5fcULL, 0xbd4c4b8fbbce2b07ULL, 0xa1246df34abe7b49ULL, + 0x7d5569b79be9af3cULL, 0xa9b5a705bd9efa12ULL, 0xdb6b835baa4bc0e8ULL, + 0x05793bac8f147342ULL, 0x21c1512881848390ULL, 0xfdb0556c50d357e5ULL, + 0x613d4fcb6a99ff72ULL, 0x03dce2648e0cda3eULL, 0xe949b9e6568386f0ULL, + 0xfc0f0bbb2ad7ea04ULL, 0x6a70675913b5a417ULL, 0x7f36d5046fe1c8e3ULL, + 0x0c57af8d02304ff8ULL, 0x32223abdfcc84618ULL, 0x0891caf6f720815bULL, + 0xa63eeaec31a26fd4ULL, 0x2507345374944d33ULL, 0x49d28ac266394058ULL, + 0xf5219f9aa7f3d6beULL, 0x2d96fea583b4cc68ULL, 0x5a31e1571b7585d0ULL, + 0x8ed12fe53d02d0feULL, 0xdfade6205f5b0e4bULL, 0x4cabb16ee92d331aULL, + 0x04c6657bf510cea3ULL, 0xd73c2cd6a87b8f10ULL, 0xe1d87310a1a307abULL, + 0x6cd5be9112ad0d6bULL, 0x97c032354366f3f2ULL, 0xd4e0ceb22677552eULL, + 0x0000000000000000ULL, 0x29509bde76a402cbULL, 0xc27a9e8bd42fe3e4ULL, + 0x5ef7842cee654b73ULL, 0xaf107ecdbc86536eULL, 0x3fcacbe784fcb401ULL, + 0xd55f90655c73e8cfULL, 0xe6c2f40fdabf1336ULL, 0xe8f6e7312c873b11ULL, + 0xeb2a0555a28be12fULL, 0xe4a148bc2eb774e9ULL, 0x9b979db84156bc0aULL, + 0x6eb60222e6a56ab4ULL, 0x87ffbbc4b026ec44ULL, 0xc703a5275b3b90a6ULL, + 0x47e699fc9001687fULL, 0x9c8d1aa73a4aa897ULL, 0x7cea3760e1ed12ddULL, + 0x4ec80ddd1d2554c5ULL, 0x13e36b957d4cc588ULL, 0x5d2b66486069914dULL, + 0x92b90999cc7280b0ULL, 0x517cc9c56259deb5ULL, 0xc937b619ad03b881ULL, + 0xec30824ad997f5b2ULL, 0xa45d565fc5aa080bULL, 0xd6837201d27f32f1ULL, + 0x635ef3789e9198adULL, 0x531f75769651b96aULL, 0x4f77530a6721e924ULL, + 0x486dd4151c3dfdb9ULL, 0x5f48dafb9461f692ULL, 0x375b011173dc355aULL, + 0x3da9775470f4d3deULL, 0x8d0dcd81b30e0ac0ULL, 0x36e45fc609d888bbULL, + 0x55baacbe97491016ULL, 0x8cb29356c90ab721ULL, 0x76184125e2c5f459ULL, + 0x99f4210bb55edbd5ULL, 0x6f095cf59ca1d755ULL, 0x9f51f8c3b44672a9ULL, + 0x3538bda287d45285ULL, 0x50c39712185d6354ULL, 0xf23b1885dcefc223ULL, + 0x79930ccc6ef9619fULL, 0xed8fdc9da3934853ULL, 0xcb540aaa590bdf5eULL, + 0x5c94389f1a6d2cacULL, 0xe77daad8a0bbaed7ULL, 0x28efc5090ca0bf2aULL, + 0xbf2ff73c4fc64cd8ULL, 0xb37858b14df60320ULL, 0xf8c96ec0dfc724a7ULL, + 0x828680683f329f06ULL, 0x941cd051cd6a29ccULL, 0xc3c5c05cae2b5e05ULL, + 0xb601631dc2e27062ULL, 0xc01922382027843bULL, 0x24b86a840e90f0d2ULL, + 0xd245177a276ffc52ULL, 0x0f8b4de98c3c95c6ULL, 0x3e759530fef809e0ULL, + 0x0b4d2892792c5b65ULL, 0xc4df4743d5374a98ULL, 0xa5e20888bfaeb5eaULL, + 0xba56cc90c0d23f9aULL, 0x38d04cf8ffe0a09cULL, 0x62e1adafe495254cULL, + 0x0263bcb3f40867dfULL, 0xcaeb547d230f62bfULL, 0x6082111c109d4293ULL, + 0xdad4dd8cd04f7d09ULL, 0xefec602e579b2f8cULL, 0x1fb4c4187f7c8a70ULL, + 0xffd3e9dfa4db303aULL, 0x7bf0b07f9af10640ULL, 0xf49ec14dddf76b5fULL, + 0x8f6e713247066d1fULL, 0x339d646a86ccfbf9ULL, 0x64447467e58d8c30ULL, + 0x2c29a072f9b07189ULL, 0xd8b7613f24471ad6ULL, 0x6627c8d41185ebefULL, + 0xa347d140beb61c96ULL, 0xde12b8f7255fb3aaULL, 0x9d324470404e1576ULL, + 0x9306574eb6763d51ULL, 0xa80af9d2c79a47f3ULL, 0x859c0777442e8b9bULL, + 0x69ac853d9db97e29ULL + }, { + 0xc3407dfc2de6377eULL, 0x5b9e93eea4256f77ULL, 0xadb58fdd50c845e0ULL, + 0x5219ff11a75bed86ULL, 0x356b61cfd90b1de9ULL, 0xfb8f406e25abe037ULL, + 0x7a5a0231c0f60796ULL, 0x9d3cd216e1f5020bULL, 0x0c6550fb6b48d8f3ULL, + 0xf57508c427ff1c62ULL, 0x4ad35ffa71cb407dULL, 0x6290a2da1666aa6dULL, + 0xe284ec2349355f9fULL, 0xb3c307c53d7c84ecULL, 0x05e23c0468365a02ULL, + 0x190bac4d6c9ebfa8ULL, 0x94bbbee9e28b80faULL, 0xa34fc777529cb9b5ULL, + 0xcc7b39f095bcd978ULL, 0x2426addb0ce532e3ULL, 0x7e79329312ce4fc7ULL, + 0xab09a72eebec2917ULL, 0xf8d15499f6b9d6c2ULL, 0x1a55b8babf8c895dULL, + 0xdb8add17fb769a85ULL, 0xb57f2f368658e81bULL, 0x8acd36f18f3f41f6ULL, + 0x5ce3b7bba50f11d3ULL, 0x114dcc14d5ee2f0aULL, 0xb91a7fcded1030e8ULL, + 0x81d5425fe55de7a1ULL, 0xb6213bc1554adeeeULL, 0x80144ef95f53f5f2ULL, + 0x1e7688186db4c10cULL, 0x3b912965db5fe1bcULL, 0xc281715a97e8252dULL, + 0x54a5d7e21c7f8171ULL, 0x4b12535ccbc5522eULL, 0x1d289cefbea6f7f9ULL, + 0x6ef5f2217d2e729eULL, 0xe6a7dc819b0d17ceULL, 0x1b94b41c05829b0eULL, + 0x33d7493c622f711eULL, 0xdcf7f942fa5ce421ULL, 0x600fba8b7f7a8ecbULL, + 0x46b60f011a83988eULL, 0x235b898e0dcf4c47ULL, 0x957ab24f588592a9ULL, + 0x4354330572b5c28cULL, 0xa5f3ef84e9b8d542ULL, 0x8c711e02341b2d01ULL, + 0x0b1874ae6a62a657ULL, 0x1213d8e306fc19ffULL, 0xfe6d7c6a4d9dba35ULL, + 0x65ed868f174cd4c9ULL, 0x88522ea0e6236550ULL, 0x899322065c2d7703ULL, + 0xc01e690bfef4018bULL, 0x915982ed8abddaf8ULL, 0xbe675b98ec3a4e4cULL, + 0xa996bf7f82f00db1ULL, 0xe1daf8d49a27696aULL, 0x2effd5d3dc8986e7ULL, + 0xd153a51f2b1a2e81ULL, 0x18caa0ebd690adfbULL, 0x390e3134b243c51aULL, + 0x2778b92cdff70416ULL, 0x029f1851691c24a6ULL, 0x5e7cafeacc133575ULL, + 0xfa4e4cc89fa5f264ULL, 0x5a5f9f481e2b7d24ULL, 0x484c47ab18d764dbULL, + 0x400a27f2a1a7f479ULL, 0xaeeb9b2a83da7315ULL, 0x721c626879869734ULL, + 0x042330a2d2384851ULL, 0x85f672fd3765aff0ULL, 0xba446b3a3e02061dULL, + 0x73dd6ecec3888567ULL, 0xffac70ccf793a866ULL, 0xdfa9edb5294ed2d4ULL, + 0x6c6aea7014325638ULL, 0x834a5a0e8c41c307ULL, 0xcdba35562fb2cb2bULL, + 0x0ad97808d06cb404ULL, 0x0f3b440cb85aee06ULL, 0xe5f9c876481f213bULL, + 0x98deee1289c35809ULL, 0x59018bbfcd394bd1ULL, 0xe01bf47220297b39ULL, + 0xde68e1139340c087ULL, 0x9fa3ca4788e926adULL, 0xbb85679c840c144eULL, + 0x53d8f3b71d55ffd5ULL, 0x0da45c5dd146caa0ULL, 0x6f34fe87c72060cdULL, + 0x57fbc315cf6db784ULL, 0xcee421a1fca0fddeULL, 0x3d2d0196607b8d4bULL, + 0x642c8a29ad42c69aULL, 0x14aff010bdd87508ULL, 0xac74837beac657b3ULL, + 0x3216459ad821634dULL, 0x3fb219c70967a9edULL, 0x06bc28f3bb246cf7ULL, + 0xf2082c9126d562c6ULL, 0x66b39278c45ee23cULL, 0xbd394f6f3f2878b9ULL, + 0xfd33689d9e8f8cc0ULL, 0x37f4799eb017394fULL, 0x108cc0b26fe03d59ULL, + 0xda4bd1b1417888d6ULL, 0xb09d1332ee6eb219ULL, 0x2f3ed975668794b4ULL, + 0x58c0871977375982ULL, 0x7561463d78ace990ULL, 0x09876cff037e82f1ULL, + 0x7fb83e35a8c05d94ULL, 0x26b9b58a65f91645ULL, 0xef20b07e9873953fULL, + 0x3148516d0b3355b8ULL, 0x41cb2b541ba9e62aULL, 0x790416c613e43163ULL, + 0xa011d380818e8f40ULL, 0x3a5025c36151f3efULL, 0xd57095bdf92266d0ULL, + 0x498d4b0da2d97688ULL, 0x8b0c3a57353153a5ULL, 0x21c491df64d368e1ULL, + 0x8f2f0af5e7091bf4ULL, 0x2da1c1240f9bb012ULL, 0xc43d59a92ccc49daULL, + 0xbfa6573e56345c1fULL, 0x828b56a8364fd154ULL, 0x9a41f643e0df7cafULL, + 0xbcf843c985266aeaULL, 0x2b1de9d7b4bfdce5ULL, 0x20059d79dedd7ab2ULL, + 0x6dabe6d6ae3c446bULL, 0x45e81bf6c991ae7bULL, 0x6351ae7cac68b83eULL, + 0xa432e32253b6c711ULL, 0xd092a9b991143cd2ULL, 0xcac711032e98b58fULL, + 0xd8d4c9e02864ac70ULL, 0xc5fc550f96c25b89ULL, 0xd7ef8dec903e4276ULL, + 0x67729ede7e50f06fULL, 0xeac28c7af045cf3dULL, 0xb15c1f945460a04aULL, + 0x9cfddeb05bfb1058ULL, 0x93c69abce3a1fe5eULL, 0xeb0380dc4a4bdd6eULL, + 0xd20db1e8f8081874ULL, 0x229a8528b7c15e14ULL, 0x44291750739fbc28ULL, + 0xd3ccbd4e42060a27ULL, 0xf62b1c33f4ed2a97ULL, 0x86a8660ae4779905ULL, + 0xd62e814a2a305025ULL, 0x477703a7a08d8addULL, 0x7b9b0e977af815c5ULL, + 0x78c51a60a9ea2330ULL, 0xa6adfb733aaae3b7ULL, 0x97e5aa1e3199b60fULL, + 0x0000000000000000ULL, 0xf4b404629df10e31ULL, 0x5564db44a6719322ULL, + 0x9207961a59afec0dULL, 0x9624a6b88b97a45cULL, 0x363575380a192b1cULL, + 0x2c60cd82b595a241ULL, 0x7d272664c1dc7932ULL, 0x7142769faa94a1c1ULL, + 0xa1d0df263b809d13ULL, 0x1630e841d4c451aeULL, 0xc1df65ad44fa13d8ULL, + 0x13d2d445bcf20bacULL, 0xd915c546926abe23ULL, 0x38cf3d92084dd749ULL, + 0xe766d0272103059dULL, 0xc7634d5effde7f2fULL, 0x077d2455012a7ea4ULL, + 0xedbfa82ff16fb199ULL, 0xaf2a978c39d46146ULL, 0x42953fa3c8bbd0dfULL, + 0xcb061da59496a7dcULL, 0x25e7a17db6eb20b0ULL, 0x34aa6d6963050fbaULL, + 0xa76cf7d580a4f1e4ULL, 0xf7ea10954ee338c4ULL, 0xfcf2643b24819e93ULL, + 0xcf252d0746aeef8dULL, 0x4ef06f58a3f3082cULL, 0x563acfb37563a5d7ULL, + 0x5086e740ce47c920ULL, 0x2982f186dda3f843ULL, 0x87696aac5e798b56ULL, + 0x5d22bb1d1f010380ULL, 0x035e14f7d31236f5ULL, 0x3cec0d30da759f18ULL, + 0xf3c920379cdb7095ULL, 0xb8db736b571e22bbULL, 0xdd36f5e44052f672ULL, + 0xaac8ab8851e23b44ULL, 0xa857b3d938fe1fe2ULL, 0x17f1e4e76eca43fdULL, + 0xec7ea4894b61a3caULL, 0x9e62c6e132e734feULL, 0xd4b1991b432c7483ULL, + 0x6ad6c283af163acfULL, 0x1ce9904904a8e5aaULL, 0x5fbda34c761d2726ULL, + 0xf910583f4cb7c491ULL, 0xc6a241f845d06d7cULL, 0x4f3163fe19fd1a7fULL, + 0xe99c988d2357f9c8ULL, 0x8eee06535d0709a7ULL, 0x0efa48aa0254fc55ULL, + 0xb4be23903c56fa48ULL, 0x763f52caabbedf65ULL, 0xeee1bcd8227d876cULL, + 0xe345e085f33b4dccULL, 0x3e731561b369bbbeULL, 0x2843fd2067adea10ULL, + 0x2adce5710eb1ceb6ULL, 0xb7e03767ef44ccbdULL, 0x8db012a48e153f52ULL, + 0x61ceb62dc5749c98ULL, 0xe85d942b9959eb9bULL, 0x4c6f7709caef2c8aULL, + 0x84377e5b8d6bbda3ULL, 0x30895dcbb13d47ebULL, 0x74a04a9bc2a2fbc3ULL, + 0x6b17ce251518289cULL, 0xe438c4d0f2113368ULL, 0x1fb784bed7bad35fULL, + 0x9b80fae55ad16efcULL, 0x77fe5e6c11b0cd36ULL, 0xc858095247849129ULL, + 0x08466059b97090a2ULL, 0x01c10ca6ba0e1253ULL, 0x6988d6747c040c3aULL, + 0x6849dad2c60a1e69ULL, 0x5147ebe67449db73ULL, 0xc99905f4fd8a837aULL, + 0x991fe2b433cd4a5aULL, 0xf09734c04fc94660ULL, 0xa28ecbd1e892abe6ULL, + 0xf1563866f5c75433ULL, 0x4dae7baf70e13ed9ULL, 0x7ce62ac27bd26b61ULL, + 0x70837a39109ab392ULL, 0x90988e4b30b3c8abULL, 0xb2020b63877296bfULL, + 0x156efcb607d6675bULL + }, { + 0xe63f55ce97c331d0ULL, 0x25b506b0015bba16ULL, 0xc8706e29e6ad9ba8ULL, + 0x5b43d3775d521f6aULL, 0x0bfa3d577035106eULL, 0xab95fc172afb0e66ULL, + 0xf64b63979e7a3276ULL, 0xf58b4562649dad4bULL, 0x48f7c3dbae0c83f1ULL, + 0xff31916642f5c8c5ULL, 0xcbb048dc1c4a0495ULL, 0x66b8f83cdf622989ULL, + 0x35c130e908e2b9b0ULL, 0x7c761a61f0b34fa1ULL, 0x3601161cf205268dULL, + 0x9e54ccfe2219b7d6ULL, 0x8b7d90a538940837ULL, 0x9cd403588ea35d0bULL, + 0xbc3c6fea9ccc5b5aULL, 0xe5ff733b6d24aeedULL, 0xceed22de0f7eb8d2ULL, + 0xec8581cab1ab545eULL, 0xb96105e88ff8e71dULL, 0x8ca03501871a5eadULL, + 0x76ccce65d6db2a2fULL, 0x5883f582a7b58057ULL, 0x3f7be4ed2e8adc3eULL, + 0x0fe7be06355cd9c9ULL, 0xee054e6c1d11be83ULL, 0x1074365909b903a6ULL, + 0x5dde9f80b4813c10ULL, 0x4a770c7d02b6692cULL, 0x5379c8d5d7809039ULL, + 0xb4067448161ed409ULL, 0x5f5e5026183bd6cdULL, 0xe898029bf4c29df9ULL, + 0x7fb63c940a54d09cULL, 0xc5171f897f4ba8bcULL, 0xa6f28db7b31d3d72ULL, + 0x2e4f3be7716eaa78ULL, 0x0d6771a099e63314ULL, 0x82076254e41bf284ULL, + 0x2f0fd2b42733df98ULL, 0x5c9e76d3e2dc49f0ULL, 0x7aeb569619606cdbULL, + 0x83478b07b2468764ULL, 0xcfadcb8d5923cd32ULL, 0x85dac7f05b95a41eULL, + 0xb5469d1b4043a1e9ULL, 0xb821ecbbd9a592fdULL, 0x1b8e0b0e798c13c8ULL, + 0x62a57b6d9a0be02eULL, 0xfcf1b793b81257f8ULL, 0x9d94ea0bd8fe28ebULL, + 0x4cea408aeb654a56ULL, 0x23284a47e888996cULL, 0x2d8f1d128b893545ULL, + 0xf4cbac3132c0d8abULL, 0xbd7c86b9ca912ebaULL, 0x3a268eef3dbe6079ULL, + 0xf0d62f6077a9110cULL, 0x2735c916ade150cbULL, 0x89fd5f03942ee2eaULL, + 0x1acee25d2fd16628ULL, 0x90f39bab41181bffULL, 0x430dfe8cde39939fULL, + 0xf70b8ac4c8274796ULL, 0x1c53aeaac6024552ULL, 0x13b410acf35e9c9bULL, + 0xa532ab4249faa24fULL, 0x2b1251e5625a163fULL, 0xd7e3e676da4841c7ULL, + 0xa7b264e4e5404892ULL, 0xda8497d643ae72d3ULL, 0x861ae105a1723b23ULL, + 0x38a6414991048aa4ULL, 0x6578dec92585b6b4ULL, 0x0280cfa6acbaeaddULL, + 0x88bdb650c273970aULL, 0x9333bd5ebbff84c2ULL, 0x4e6a8f2c47dfa08bULL, + 0x321c954db76cef2aULL, 0x418d312a72837942ULL, 0xb29b38bfffcdf773ULL, + 0x6c022c38f90a4c07ULL, 0x5a033a240b0f6a8aULL, 0x1f93885f3ce5da6fULL, + 0xc38a537e96988bc6ULL, 0x39e6a81ac759ff44ULL, 0x29929e43cee0fce2ULL, + 0x40cdd87924de0ca2ULL, 0xe9d8ebc8a29fe819ULL, 0x0c2798f3cfbb46f4ULL, + 0x55e484223e53b343ULL, 0x4650948ecd0d2fd8ULL, 0x20e86cb2126f0651ULL, + 0x6d42c56baf5739e7ULL, 0xa06fc1405ace1e08ULL, 0x7babbfc54f3d193bULL, + 0x424d17df8864e67fULL, 0xd8045870ef14980eULL, 0xc6d7397c85ac3781ULL, + 0x21a885e1443273b1ULL, 0x67f8116f893f5c69ULL, 0x24f5efe35706cff6ULL, + 0xd56329d076f2ab1aULL, 0x5e1eb9754e66a32dULL, 0x28d2771098bd8902ULL, + 0x8f6013f47dfdc190ULL, 0x17a993fdb637553cULL, 0xe0a219397e1012aaULL, + 0x786b9930b5da8606ULL, 0x6e82e39e55b0a6daULL, 0x875a0856f72f4ec3ULL, + 0x3741ff4fa458536dULL, 0xac4859b3957558fcULL, 0x7ef6d5c75c09a57cULL, + 0xc04a758b6c7f14fbULL, 0xf9acdd91ab26ebbfULL, 0x7391a467c5ef9668ULL, + 0x335c7c1ee1319acaULL, 0xa91533b18641e4bbULL, 0xe4bf9a683b79db0dULL, + 0x8e20faa72ba0b470ULL, 0x51f907737b3a7ae4ULL, 0x2268a314bed5ec8cULL, + 0xd944b123b949edeeULL, 0x31dcb3b84d8b7017ULL, 0xd3fe65279f218860ULL, + 0x097af2f1dc8ffab3ULL, 0x9b09a6fc312d0b91ULL, 0xcc6ded78a3c4520fULL, + 0x3481d9ba5ebfcc50ULL, 0x4f2a667f1182d56bULL, 0xdfd9fdd4509ace94ULL, + 0x26752045fbbc252bULL, 0xbffc491f662bc467ULL, 0xdd593272fc202449ULL, + 0x3cbbc218d46d4303ULL, 0x91b372f817456e1fULL, 0x681faf69bc6385a0ULL, + 0xb686bbeebaa43ed4ULL, 0x1469b5084cd0ca01ULL, 0x98c98009cbca94acULL, + 0x6438379a73d8c354ULL, 0xc2caba2dc0c5fe26ULL, 0x3e3b0dbe78d7a9deULL, + 0x50b9ee202d670f04ULL, 0x4590b27b37eab0e5ULL, 0x6025b4cb36b10af3ULL, + 0xfb2c1237079c0162ULL, 0xa12f28130c936be8ULL, 0x4b37e52e54eb1cccULL, + 0x083a1ba28ad28f53ULL, 0xc10a9cd83a22611bULL, 0x9f1425ad7444c236ULL, + 0x069d4cf7e9d3237aULL, 0xedc56899e7f621beULL, 0x778c273680865fcfULL, + 0x309c5aeb1bd605f7ULL, 0x8de0dc52d1472b4dULL, 0xf8ec34c2fd7b9e5fULL, + 0xea18cd3d58787724ULL, 0xaad515447ca67b86ULL, 0x9989695a9d97e14cULL, + 0x0000000000000000ULL, 0xf196c63321f464ecULL, 0x71116bc169557cb5ULL, + 0xaf887f466f92c7c1ULL, 0x972e3e0ffe964d65ULL, 0x190ec4a8d536f915ULL, + 0x95aef1a9522ca7b8ULL, 0xdc19db21aa7d51a9ULL, 0x94ee18fa0471d258ULL, + 0x8087adf248a11859ULL, 0xc457f6da2916dd5cULL, 0xfa6cfb6451c17482ULL, + 0xf256e0c6db13fbd1ULL, 0x6a9f60cf10d96f7dULL, 0x4daaa9d9bd383fb6ULL, + 0x03c026f5fae79f3dULL, 0xde99148706c7bb74ULL, 0x2a52b8b6340763dfULL, + 0x6fc20acd03edd33aULL, 0xd423c08320afdefaULL, 0xbbe1ca4e23420dc0ULL, + 0x966ed75ca8cb3885ULL, 0xeb58246e0e2502c4ULL, 0x055d6a021334bc47ULL, + 0xa47242111fa7d7afULL, 0xe3623fcc84f78d97ULL, 0x81c744a11efc6db9ULL, + 0xaec8961539cfb221ULL, 0xf31609958d4e8e31ULL, 0x63e5923ecc5695ceULL, + 0x47107ddd9b505a38ULL, 0xa3afe7b5a0298135ULL, 0x792b7063e387f3e6ULL, + 0x0140e953565d75e0ULL, 0x12f4f9ffa503e97bULL, 0x750ce8902c3cb512ULL, + 0xdbc47e8515f30733ULL, 0x1ed3610c6ab8af8fULL, 0x5239218681dde5d9ULL, + 0xe222d69fd2aaf877ULL, 0xfe71783514a8bd25ULL, 0xcaf0a18f4a177175ULL, + 0x61655d9860ec7f13ULL, 0xe77fbc9dc19e4430ULL, 0x2ccff441ddd440a5ULL, + 0x16e97aaee06a20dcULL, 0xa855dae2d01c915bULL, 0x1d1347f9905f30b2ULL, + 0xb7c652bdecf94b34ULL, 0xd03e43d265c6175dULL, 0xfdb15ec0ee4f2218ULL, + 0x57644b8492e9599eULL, 0x07dda5a4bf8e569aULL, 0x54a46d71680ec6a3ULL, + 0x5624a2d7c4b42c7eULL, 0xbebca04c3076b187ULL, 0x7d36f332a6ee3a41ULL, + 0x3b6667bc6be31599ULL, 0x695f463aea3ef040ULL, 0xad08b0e0c3282d1cULL, + 0xb15b1e4a052a684eULL, 0x44d05b2861b7c505ULL, 0x15295c5b1a8dbfe1ULL, + 0x744c01c37a61c0f2ULL, 0x59c31cd1f1e8f5b7ULL, 0xef45a73f4b4ccb63ULL, + 0x6bdf899c46841a9dULL, 0x3dfb2b4b823036e3ULL, 0xa2ef0ee6f674f4d5ULL, + 0x184e2dfb836b8cf5ULL, 0x1134df0a5fe47646ULL, 0xbaa1231d751f7820ULL, + 0xd17eaa81339b62bdULL, 0xb01bf71953771daeULL, 0x849a2ea30dc8d1feULL, + 0x705182923f080955ULL, 0x0ea757556301ac29ULL, 0x041d83514569c9a7ULL, + 0x0abad4042668658eULL, 0x49b72a88f851f611ULL, 0x8a3d79f66ec97dd7ULL, + 0xcd2d042bf59927efULL, 0xc930877ab0f0ee48ULL, 0x9273540deda2f122ULL, + 0xc797d02fd3f14261ULL, 0xe1e2f06a284d674aULL, 0xd2be8c74c97cfd80ULL, + 0x9a494faf67707e71ULL, 0xb3dbd1eca9908293ULL, 0x72d14d3493b2e388ULL, + 0xd6a30f258c153427ULL + } +}; /* Ax */ + +static void streebog_xor(const struct streebog_uint512 *x, const struct streebog_uint512 *y, struct streebog_uint512 *z) +{ + z->qword[0] = x->qword[0] ^ y->qword[0]; + z->qword[1] = x->qword[1] ^ y->qword[1]; + z->qword[2] = x->qword[2] ^ y->qword[2]; + z->qword[3] = x->qword[3] ^ y->qword[3]; + z->qword[4] = x->qword[4] ^ y->qword[4]; + z->qword[5] = x->qword[5] ^ y->qword[5]; + z->qword[6] = x->qword[6] ^ y->qword[6]; + z->qword[7] = x->qword[7] ^ y->qword[7]; +} + +static void streebog_xlps(const struct streebog_uint512 *x, const struct streebog_uint512 *y, struct streebog_uint512 *data) +{ + uint64_t r0, r1, r2, r3, r4, r5, r6, r7; + int i; + + r0 = letoh64(x->qword[0] ^ y->qword[0]); + r1 = letoh64(x->qword[1] ^ y->qword[1]); + r2 = letoh64(x->qword[2] ^ y->qword[2]); + r3 = letoh64(x->qword[3] ^ y->qword[3]); + r4 = letoh64(x->qword[4] ^ y->qword[4]); + r5 = letoh64(x->qword[5] ^ y->qword[5]); + r6 = letoh64(x->qword[6] ^ y->qword[6]); + r7 = letoh64(x->qword[7] ^ y->qword[7]); + + for (i = 0; i <= 7; i++) { + data->qword[i] = htole64(Ax[0][r0 & 0xFF]); + data->qword[i] ^= htole64(Ax[1][r1 & 0xFF]); + data->qword[i] ^= htole64(Ax[2][r2 & 0xFF]); + data->qword[i] ^= htole64(Ax[3][r3 & 0xFF]); + data->qword[i] ^= htole64(Ax[4][r4 & 0xFF]); + data->qword[i] ^= htole64(Ax[5][r5 & 0xFF]); + data->qword[i] ^= htole64(Ax[6][r6 & 0xFF]); + data->qword[i] ^= htole64(Ax[7][r7 & 0xFF]); + r0 >>= 8; + r1 >>= 8; + r2 >>= 8; + r3 >>= 8; + r4 >>= 8; + r5 >>= 8; +r6 >>= 8; +r7 >>= 8; + } +} + +static void streebog_round(int i, struct streebog_uint512 *Ki, struct streebog_uint512 *data) +{ + streebog_xlps(Ki, &C[i], Ki); + streebog_xlps(Ki, data, data); +} + +static void streebog_pad(StreebogContext *ctx) +{ + if (ctx->fillsize >= STREEBOG_BLOCK_SIZE) + return; + osMemset(ctx->buffer + ctx->fillsize, 0, sizeof(ctx->buffer) - ctx->fillsize); + ctx->buffer[ctx->fillsize] = 1; +} + +static void streebog_add512(const struct streebog_uint512 *x, const struct streebog_uint512 *y, struct streebog_uint512 *r) +{ + uint64_t carry = 0; + int i; + + for (i = 0; i < 8; i++) { + const uint64_t left = letoh64(x->qword[i]); + uint64_t sum; + + sum = left + letoh64(y->qword[i]) + carry; + if (sum != left) + carry = (sum < left); + r->qword[i] = htole64(sum); + } +} + +static void streebog_g(struct streebog_uint512 *h, const struct streebog_uint512 *N, const struct streebog_uint512 *m) +{ + struct streebog_uint512 Ki, data; + unsigned int i; + + streebog_xlps(h, N, &data); + + /* Starting E() */ + Ki = data; + streebog_xlps(&Ki, m, &data); + + for (i = 0; i < 11; i++) + streebog_round(i, &Ki, &data); + + streebog_xlps(&Ki, &C[11], &Ki); + streebog_xor(&Ki, &data, &data); + /* E() done */ + + streebog_xor(&data, h, &data); + streebog_xor(&data, m, h); +} + +static void streebog_stage2(StreebogContext *ctx, const uint8_t *data) +{ + struct streebog_uint512 m; + + osMemcpy(&m, data, sizeof(m)); + + streebog_g(&ctx->h, &ctx->N, &m); + + streebog_add512(&ctx->N, &buffer512, &ctx->N); + streebog_add512(&ctx->Sigma, &m, &ctx->Sigma); +} + +static void streebog_stage3(StreebogContext *ctx) +{ + struct streebog_uint512 buf = { { 0 } }; + + buf.qword[0] = htole64(ctx->fillsize << 3); + streebog_pad(ctx); + + streebog_g(&ctx->h, &ctx->N, &ctx->m); + streebog_add512(&ctx->N, &buf, &ctx->N); + streebog_add512(&ctx->Sigma, &ctx->m, &ctx->Sigma); + streebog_g(&ctx->h, &buffer0, &ctx->N); + streebog_g(&ctx->h, &buffer0, &ctx->Sigma); + osMemcpy(&ctx->hash, &ctx->h, sizeof(struct streebog_uint512)); +} + +static void streebog_init(StreebogContext *ctx, size_t size) +{ + unsigned int i; + + osMemset(ctx, 0, sizeof(StreebogContext)); + if (size == STREEBOG256_DIGEST_SIZE) + ctx->digest_size = STREEBOG256_DIGEST_SIZE; + else + ctx->digest_size = STREEBOG512_DIGEST_SIZE; + for (i = 0; i < 8; i++) { + if (ctx->digest_size == STREEBOG256_DIGEST_SIZE) + ctx->h.qword[i] = htole64(0x0101010101010101ULL); + } +} + +static error_t streebog_compute(const void *data, size_t length, uint8_t *digest, size_t size) +{ +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + StreebogContext *context; +#else + StreebogContext context[1]; +#endif + + //Check parameters + if (data == NULL && length != 0) + return ERROR_INVALID_PARAMETER; + + if (digest == NULL) + return ERROR_INVALID_PARAMETER; + +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + //Allocate a memory buffer to hold the Streebog-256 context + context = cryptoAllocMem(sizeof(StreebogContext)); + //Failed to allocate memory? + if (context == NULL) + return ERROR_OUT_OF_MEMORY; +#endif + +#if (STREEBOG256_SUPPORT == ENABLED) + if (size == STREEBOG256_DIGEST_SIZE) + //Initialize the Streebog-256 context + streebog256Init(context); + else +#endif +#if (STREEBOG512_SUPPORT == ENABLED) + //Initialize the Streebog-256 context + streebog512Init(context); +#endif + //Digest the message + streebogUpdate(context, data, length); + //Finalize the Streebog-256 message digest + streebogFinal(context, digest); + +#if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED) + //Free previously allocated memory + cryptoFreeMem(context); +#endif + + //Successful processing + return NO_ERROR; +} + + +//Check crypto library configuration +#if (STREEBOG256_SUPPORT == ENABLED) +/** + * @brief Digest a message using Streebog-256 + * @param[in] data Pointer to the message being hashed + * @param[in] length Length of the message + * @param[out] digest Pointer to the calculated digest + * @return Error code + **/ + +__weak_func error_t streebog256Compute(const void *data, size_t length, uint8_t *digest) +{ + return streebog_compute(data, length, digest, STREEBOG256_DIGEST_SIZE); +} +#endif + + +//Check crypto library configuration +#if (STREEBOG512_SUPPORT == ENABLED) +/** + * @brief Digest a message using Streebog-256 + * @param[in] data Pointer to the message being hashed + * @param[in] length Length of the message + * @param[out] digest Pointer to the calculated digest + * @return Error code + **/ + +__weak_func error_t streebog512Compute(const void *data, size_t length, uint8_t *digest) +{ + return streebog_compute(data, length, digest, STREEBOG512_DIGEST_SIZE); +} +#endif + + +/** + * @brief Initialize Streebog-256 message digest context + * @param[in] ctx Pointer to the Sstreebog-256 context to initialize + **/ + +__weak_func void streebog256Init(StreebogContext *ctx) +{ + streebog_init(ctx, STREEBOG256_DIGEST_SIZE); +} + +/** + * @brief Initialize Streebog-512 message digest context + * @param[in] ctx Pointer to the Sstreebog-512 context to initialize + **/ + +__weak_func void streebog512Init(StreebogContext *ctx) +{ + streebog_init(ctx, STREEBOG512_DIGEST_SIZE); +} + + +/** + * @brief Update the Streebog-256 context with a portion of the message being hashed + * @param[in] ctx Pointer to the Streebog-256 context + * @param[in] buf Pointer to the buffer being hashed + * @param[in] len Length of the buffer + **/ + +__weak_func void streebogUpdate(StreebogContext *ctx, const void *buf, size_t len) +{ + size_t chunksize; + uint8_t *data = (uint8_t *)buf; + + if (ctx->fillsize) { + chunksize = STREEBOG_BLOCK_SIZE - ctx->fillsize; + if (chunksize > len) + chunksize = len; + osMemcpy(&ctx->buffer[ctx->fillsize], data, chunksize); + ctx->fillsize += chunksize; + len -= chunksize; + data += chunksize; + + if (ctx->fillsize == STREEBOG_BLOCK_SIZE) { + streebog_stage2(ctx, ctx->buffer); + ctx->fillsize = 0; + } + } + + while (len >= STREEBOG_BLOCK_SIZE) { + streebog_stage2(ctx, data); + data += STREEBOG_BLOCK_SIZE; + len -= STREEBOG_BLOCK_SIZE; + } + + if (len) { + osMemcpy(&ctx->buffer, data, len); + ctx->fillsize = len; + } +} + + +/** + * @brief Finish the Streebog-256 message digest + * @param[in] ctx Pointer to the Streebog-256 context + * @param[out] digest Calculated digest (optional parameter) + **/ + +__weak_func void streebogFinal(StreebogContext *ctx, uint8_t *digest) +{ + streebog_stage3(ctx); + ctx->fillsize = 0; + if (digest) { + if (ctx->digest_size == STREEBOG256_DIGEST_SIZE) + osMemcpy(digest, &ctx->hash.qword[4], STREEBOG256_DIGEST_SIZE); + else + osMemcpy(digest, &ctx->hash.qword[0], STREEBOG512_DIGEST_SIZE); + } +} + +#endif diff --git a/hash/streebog.h b/hash/streebog.h new file mode 100644 index 00000000..c60954f6 --- /dev/null +++ b/hash/streebog.h @@ -0,0 +1,127 @@ +/** + * @file streebog.h + * @brief Streebog-256/512 hash function + * + * Streebog-256/512 hash function as specified by GOST R 34.11-2012 and + * described at https://tools.ietf.org/html/rfc6986 + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2013 Alexey Degtyarev + * Copyright (c) 2018 Vitaly Chikunov + * Copyright (c) 2024 Valery Novikov + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Valery Novikov + * @version 2.4.0 + **/ + +#ifndef _STREEBOG_H +#define _STREEBOG_H + +//Dependencies +#include "core/crypto.h" + +//Application specific context +#ifndef STREEBOG256_PRIVATE_CONTEXT + #define STREEBOG256_PRIVATE_CONTEXT +#endif + +//Minimum length of the padding string +#define STREEBOG256_MIN_PAD_SIZE 0 // TODO: ??? +#define STREEBOG512_MIN_PAD_SIZE 0 // TODO: ??? +//Streebog-256/512 block size +#define STREEBOG_BLOCK_SIZE 64 +//Streebog-256 digest size +#define STREEBOG256_DIGEST_SIZE 32 +//Streebog-512 digest size +#define STREEBOG512_DIGEST_SIZE 64 + +#if (STREEBOG256_SUPPORT == ENABLED) +//Common interface for hash algorithms +#define STREEBOG256_HASH_ALGO (&streebog256HashAlgo) +#endif +#if (STREEBOG512_SUPPORT == ENABLED) +//Common interface for hash algorithms +#define STREEBOG512_HASH_ALGO (&streebog512HashAlgo) +#endif + +//C++ guard +#ifdef __cplusplus +extern "C" { +#endif + +struct streebog_uint512 { + uint64_t qword[8]; +}; + + +/** + * @brief Streebog algorithm context + **/ + +typedef struct +{ + union + { + uint32_t b[16]; + uint8_t digest[64]; + struct streebog_uint512 hash; + }; + union + { + uint8_t buffer[STREEBOG_BLOCK_SIZE]; + struct streebog_uint512 m; + }; + struct streebog_uint512 h; + struct streebog_uint512 N; + struct streebog_uint512 Sigma; + size_t fillsize; + size_t digest_size; + STREEBOG256_PRIVATE_CONTEXT +} StreebogContext; + + +//Streebog related constants +#if (STREEBOG256_SUPPORT == ENABLED) +extern const uint8_t STREEBOG256_OID[10]; +extern const HashAlgo streebog256HashAlgo; + +error_t streebog256Compute(const void *data, size_t length, uint8_t *digest); +void streebog256Init(StreebogContext *context); +#endif +#if (STREEBOG512_SUPPORT == ENABLED) +extern const uint8_t STREEBOG512_OID[10]; +extern const HashAlgo streebog512HashAlgo; + +error_t streebog512Compute(const void *data, size_t length, uint8_t *digest); +void streebog512Init(StreebogContext *context); +#endif + +//Streebog related functions +void streebogUpdate(StreebogContext *context, const void *data, size_t length); +void streebogFinal(StreebogContext *context, uint8_t *digest); + +//C++ guard +#ifdef __cplusplus +} +#endif + +#endif From 2cb42cd6425247089d7f26d1e65c80059899de9d Mon Sep 17 00:00:00 2001 From: Novikov Valerii Date: Fri, 16 Feb 2024 21:50:45 +0500 Subject: [PATCH 2/8] Added ECRDSA (Elliptic Curve Russian Digital Signature Algorithm) /** * TODO: * ecrdsaWriteSignature * ecrdsaReadSignature * OIDs * NIST Curves * X509 support **/ --- core/crypto.h | 7 + ecc/ecrdsa.c | 849 ++++++++++++++++++++++++++++++++++++++++++ ecc/ecrdsa.h | 102 +++++ pkc/sign_algorithms.h | 5 + 4 files changed, 963 insertions(+) create mode 100644 ecc/ecrdsa.c create mode 100644 ecc/ecrdsa.h diff --git a/core/crypto.h b/core/crypto.h index 05cb6e78..5e9f6fbb 100644 --- a/core/crypto.h +++ b/core/crypto.h @@ -669,6 +669,13 @@ #error ECDSA_SUPPORT parameter is not valid #endif +//ECRDSA support +#ifndef ECRDSA_SUPPORT +#define ECRDSA_SUPPORT ENABLED +#elif (ECRDSA_SUPPORT != ENABLED && ECRDSA_SUPPORT != DISABLED) +#error ECRDSA_SUPPORT parameter is not valid +#endif + //Streamlined NTRU Prime 761 KEM support #ifndef SNTRUP761_SUPPORT #define SNTRUP761_SUPPORT DISABLED diff --git a/ecc/ecrdsa.c b/ecc/ecrdsa.c new file mode 100644 index 00000000..79b64030 --- /dev/null +++ b/ecc/ecrdsa.c @@ -0,0 +1,849 @@ +/** + * @file ecrdsa.c + * @brief ECRDSA (Elliptic Curve Russian Digital Signature Algorithm) + * + * Elliptic Curve (Russian) Digital Signature Algorithm for Cryptographic API + * + * Copyright (c) 2024 Valery Novikov + * + * References: + * GOST 34.10-2018, GOST R 34.10-2012, RFC 7091, ISO/IEC 14888-3:2018. + * + * Historical references: + * GOST R 34.10-2001, RFC 4357, ISO/IEC 14888-3:2006/Amd 1:2010. + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Valery Novikov + * @version 2.4.0 + **/ + +/** + * TODO: + * ecrdsaWriteSignature + * ecrdsaReadSignature + * OIDs + * NIST Curves + * X509 support + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL CRYPTO_TRACE_LEVEL//TRACE_LEVEL_VERBOSE//CRYPTO_TRACE_LEVEL + +//Dependencies +#include "core/crypto.h" +#include "ecc/ecrdsa.h" +#include "mpi/mpi.h" +#include "encoding/asn1.h" +#include "debug.h" + +//Check crypto library configuration +#if (ECRDSA_SUPPORT == ENABLED) +/* TODO: временно для порта +//ECDSA with SHA-1 OID (1.2.840.10045.4.1) +const uint8_t ECDSA_WITH_SHA1_OID[7] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x01}; +//ECDSA with SHA-224 OID (1.2.840.10045.4.3.1) +const uint8_t ECDSA_WITH_SHA224_OID[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x01}; +//ECDSA with SHA-256 OID (1.2.840.10045.4.3.2) +const uint8_t ECDSA_WITH_SHA256_OID[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02}; +//ECDSA with SHA-384 OID (1.2.840.10045.4.3.3) +const uint8_t ECDSA_WITH_SHA384_OID[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03}; +//ECDSA with SHA-512 OID (1.2.840.10045.4.3.4) +const uint8_t ECDSA_WITH_SHA512_OID[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x04}; +//ECDSA with SHA-3-224 OID (2.16.840.1.101.3.4.3.9) +const uint8_t ECDSA_WITH_SHA3_224_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x09}; +//ECDSA with SHA-3-256 OID (2.16.840.1.101.3.4.3.10) +const uint8_t ECDSA_WITH_SHA3_256_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0A}; +//ECDSA with SHA-3-384 OID (2.16.840.1.101.3.4.3.11) +const uint8_t ECDSA_WITH_SHA3_384_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0B}; +//ECDSA with SHA-3-512 OID (2.16.840.1.101.3.4.3.12) +const uint8_t ECDSA_WITH_SHA3_512_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x0C}; +*/ + +static inline error_t ecrdsaGenerateSignatureStep4(const EcDomainParameters *params, const Mpi *k, EcPoint *C, EcrdsaSignature *signature) +{ + error_t error; + // Step 4: Compute the point of the elliptic curve C = kP and determine r = Xc (mod q), where – Xc is the coordinate of point C. If r = 0, then go back to step 3. + EC_CHECK(ecMult(params, C, k, ¶ms->g)); + EC_CHECK(ecAffinify(params, C, C)); + MPI_CHECK(mpiMod(&signature->r, &C->x, ¶ms->q)); + return NO_ERROR; +end: + return error; +} + +static inline error_t ecrdsaGenerateSignatureStep5(const Mpi *d, const Mpi *e, Mpi *k, const Mpi *q, EcrdsaSignature *signature) +{ + error_t error; + // Step 5: Compute the value of s ≡ (rd + ke)(mod q). If s = 0, then go back to step 3. + MPI_CHECK(mpiMul(&signature->s, &signature->r, d)); + MPI_CHECK(mpiMul(k, k, e)); + MPI_CHECK(mpiAdd(&signature->s, &signature->s, k)); + MPI_CHECK(mpiMod(&signature->s, &signature->s, q)); + return NO_ERROR; +end: + return error; +} + +static inline error_t ecrdsaVerifySignatureFinal(const EcDomainParameters *params, const EcPoint *Q, const Mpi *e, EcrdsaSignature *signature) +{ + error_t error = NO_ERROR; + Mpi v; + Mpi z1; + Mpi z2; + EcPoint C; + + //Initialize multiple precision integers + mpiInit(&v); + mpiInit(&z1); + mpiInit(&z2); + //Initialize EC points + ecInit(&C); + + // Step 4: Compute v = e ^ -1 mod q + MPI_CHECK(mpiInvMod(&v, e, ¶ms->q)); + // Step 5: Compute z1 = s * v mod q + MPI_CHECK(mpiMulMod(&z1, &signature->s, &v, ¶ms->q)); + // Compute z2 = -r * v mod q + signature->r.sign = -1; + MPI_CHECK(mpiMulMod(&z2, &signature->r, &v, ¶ms->q)); + signature->r.sign = 1; + // Step 6: Compute C = z1 * G + z2 * Q + EC_CHECK(ecProjectify(params, &C, Q)); + EC_CHECK(ecTwinMult(params, &C, &z1, ¶ms->g, &z2, Q)); + EC_CHECK(ecAffinify(params, &C, &C)); + // Debug message + TRACE_DEBUG(" Cx:\r\n"); + TRACE_DEBUG_MPI(" ", &C.x); + TRACE_DEBUG(" Cy:\r\n"); + TRACE_DEBUG_MPI(" ", &C.y); + // Step 7: Compute R = Cx mod q + MPI_CHECK(mpiMod(&v, &C.x, ¶ms->q)); + + //Debug message + TRACE_DEBUG(" R:\r\n"); + TRACE_DEBUG_MPI(" ", &v); + + //If v = r, then the signature is verified. If v does not equal r, + //then the message or the signature may have been modified + if (mpiComp(&v, &signature->r)) + error = ERROR_INVALID_SIGNATURE; +end: + return error; +} + +/** + * @brief Initialize an ECRDSA signature + * @param[in] signature Pointer to the ECRDSA signature to initialize + **/ + +void ecrdsaInitSignature(EcrdsaSignature *signature) +{ + //Initialize multiple precision integers + mpiInit(&signature->r); + mpiInit(&signature->s); +} + + +/** + * @brief Release an ECRDSA signature + * @param[in] signature Pointer to the ECRDSA signature to free + **/ + +void ecrdsaFreeSignature(EcrdsaSignature *signature) +{ + //Release multiple precision integers + mpiFree(&signature->r); + mpiFree(&signature->s); +} + + +/** + * @brief Encode ECRDSA signature using ASN.1 + * @param[in] signature (R, S) integer pair + * @param[out] data Pointer to the buffer where to store the resulting ASN.1 structure + * @param[out] length Length of the ASN.1 structure + * @return Error code + **/ + +error_t ecrdsaWriteSignature(const EcrdsaSignature *signature, uint8_t *data, + size_t *length) +{ + error_t error; + size_t k; + size_t n; + size_t rLen; + size_t sLen; + Asn1Tag tag; + + //Debug message + TRACE_INFO("Writing ECRDSA signature...\r\n"); + + //Dump (R, S) integer pair + TRACE_DEBUG(" r:\r\n"); + TRACE_DEBUG_MPI(" ", &signature->r); + TRACE_DEBUG(" s:\r\n"); + TRACE_DEBUG_MPI(" ", &signature->s); + + //Calculate the length of R + rLen = mpiGetByteLength(&signature->r); + //Calculate the length of S + sLen = mpiGetByteLength(&signature->s); + + //Make sure the (R, S) integer pair is valid + if(rLen == 0 || sLen == 0) + return ERROR_INVALID_LENGTH; + + //R and S are always encoded in the smallest possible number of octets + if(mpiGetBitValue(&signature->r, (rLen * 8) - 1)) + { + rLen++; + } + + if(mpiGetBitValue(&signature->s, (sLen * 8) - 1)) + { + sLen++; + } + + //The first pass computes the length of the ASN.1 sequence + n = 0; + + //The parameter R is encapsulated within an ASN.1 structure + tag.constructed = FALSE; + tag.objClass = ASN1_CLASS_UNIVERSAL; + tag.objType = ASN1_TYPE_INTEGER; + tag.length = rLen; + tag.value = NULL; + + //Compute the length of the corresponding ASN.1 structure + error = asn1WriteTag(&tag, FALSE, NULL, NULL); + //Any error to report? + if(error) + return error; + + //Update the length of the ASN.1 sequence + n += tag.totalLength; + + //The parameter S is encapsulated within an ASN.1 structure + tag.constructed = FALSE; + tag.objClass = ASN1_CLASS_UNIVERSAL; + tag.objType = ASN1_TYPE_INTEGER; + tag.length = sLen; + tag.value = NULL; + + //Compute the length of the corresponding ASN.1 structure + error = asn1WriteTag(&tag, FALSE, NULL, NULL); + //Any error to report? + if(error) + return error; + + //Update the length of the ASN.1 sequence + n += tag.totalLength; + + //The second pass encodes the ASN.1 structure + k = 0; + + //The (R, S) integer pair is encapsulated within a sequence + tag.constructed = TRUE; + tag.objClass = ASN1_CLASS_UNIVERSAL; + tag.objType = ASN1_TYPE_SEQUENCE; + tag.length = n; + tag.value = NULL; + + //Write the corresponding ASN.1 tag + error = asn1WriteTag(&tag, FALSE, data + k, &n); + //Any error to report? + if(error) + return error; + + //Advance write pointer + k += n; + + //Encode the parameter R using ASN.1 + tag.constructed = FALSE; + tag.objClass = ASN1_CLASS_UNIVERSAL; + tag.objType = ASN1_TYPE_INTEGER; + tag.length = rLen; + tag.value = NULL; + + //Write the corresponding ASN.1 tag + error = asn1WriteTag(&tag, FALSE, data + k, &n); + //Any error to report? + if(error) + return error; + + //Advance write pointer + k += n; + + //Convert R to an octet string + error = mpiWriteRaw(&signature->r, data + k, rLen); + //Any error to report? + if(error) + return error; + + //Advance write pointer + k += rLen; + + //Encode the parameter S using ASN.1 + tag.constructed = FALSE; + tag.objClass = ASN1_CLASS_UNIVERSAL; + tag.objType = ASN1_TYPE_INTEGER; + tag.length = sLen; + tag.value = NULL; + + //Write the corresponding ASN.1 tag + error = asn1WriteTag(&tag, FALSE, data + k, &n); + //Any error to report? + if(error) + return error; + + //Advance write pointer + k += n; + + //Convert S to an octet string + error = mpiWriteRaw(&signature->s, data + k, sLen); + //Any error to report? + if(error) + return error; + + //Advance write pointer + k += sLen; + + //Dump ECRDSA signature + TRACE_DEBUG(" signature:\r\n"); + TRACE_DEBUG_ARRAY(" ", data, k); + + //Total length of the ASN.1 structure + *length = k; + //Successful processing + return NO_ERROR; +} + + +/** + * @brief Read an ASN.1 encoded ECRDSA signature + * @param[in] data Pointer to the ASN.1 structure to decode + * @param[in] length Length of the ASN.1 structure + * @param[out] signature (R, S) integer pair + * @return Error code + **/ + +error_t ecrdsaReadSignature(const uint8_t *data, size_t length, EcrdsaSignature *signature) +{ + error_t error; + Asn1Tag tag; + + //Debug message + TRACE_DEBUG("Reading ECRDSA signature...\r\n"); + + //Dump ECRDSA signature + TRACE_DEBUG(" signature:\r\n"); + TRACE_DEBUG_ARRAY(" ", data, length); + + //Start of exception handling block + do + { + //Display ASN.1 structure + error = asn1DumpObject(data, length, 0); + //Any error to report? + if(error) + break; + + //Read the contents of the ASN.1 structure + error = asn1ReadSequence(data, length, &tag); + //Failed to decode ASN.1 tag? + if(error) + break; + + //Malformed ECRDSA signature? + if(length != tag.totalLength) + { + //Report an error + error = ERROR_INVALID_SYNTAX; + break; + } + + //Point to the first field + data = tag.value; + length = tag.length; + + //Read the parameter R + error = asn1ReadTag(data, length, &tag); + //Failed to decode ASN.1 tag? + if(error) + break; + + //Enforce encoding, class and type + error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); + //Invalid tag? + if(error) + break; + + //Make sure R is a positive integer + if(tag.length == 0 || (tag.value[0] & 0x80) != 0) + { + //Report an error + error = ERROR_INVALID_SYNTAX; + break; + } + + //Convert the octet string to a multiple precision integer + error = mpiReadRaw(&signature->r, tag.value, tag.length); + //Any error to report? + if(error) + break; + + //Point to the next field + data += tag.totalLength; + length -= tag.totalLength; + + //Read the parameter S + error = asn1ReadTag(data, length, &tag); + //Failed to decode ASN.1 tag? + if(error) + break; + + //Enforce encoding, class and type + error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); + //Invalid tag? + if(error) + break; + + //Make sure S is a positive integer + if(tag.length == 0 || (tag.value[0] & 0x80) != 0) + { + //Report an error + error = ERROR_INVALID_SYNTAX; + break; + } + + //Convert the octet string to a multiple precision integer + error = mpiReadRaw(&signature->s, tag.value, tag.length); + //Any error to report? + if(error) + break; + + //Malformed ECRDSA signature? + if(length != tag.totalLength) + { + //Report an error + error = ERROR_INVALID_SYNTAX; + break; + } + + //Dump (R, S) integer pair + TRACE_DEBUG(" r:\r\n"); + TRACE_DEBUG_MPI(" ", &signature->r); + TRACE_DEBUG(" s:\r\n"); + TRACE_DEBUG_MPI(" ", &signature->s); + + //End of exception handling block + } while(0); + + //Any error to report? + if(error) + { + //Clean up side effects + ecrdsaFreeSignature(signature); + } + + //Return status code + return error; +} + + +/** + * @brief ECRDSA signature generation + * @param[in] prngAlgo PRNG algorithm + * @param[in] prngContext Pointer to the PRNG context + * @param[in] params EC domain parameters + * @param[in] privateKey Signer's EC private key + * @param[in] digest Digest of the message to be signed + * @param[in] digestLen Length in octets of the digest + * @param[out] signature (R, S) integer pair + * @return Error code + **/ + +__weak_func error_t ecrdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, + const EcDomainParameters *params, const EcPrivateKey *privateKey, + const uint8_t *digest, size_t digestLen, EcrdsaSignature *signature) +{ + error_t error; + uint_t n; + Mpi e; + Mpi k; + EcPoint C; + + // Check parameters + if (params == NULL || privateKey == NULL || digest == NULL || signature == NULL) + return ERROR_INVALID_PARAMETER; + + //Debug message + TRACE_DEBUG("ECRDSA signature generation...\r\n"); + TRACE_DEBUG(" private key:\r\n"); + TRACE_DEBUG_MPI(" ", &privateKey->d); + TRACE_DEBUG(" digest:\r\n"); + TRACE_DEBUG_ARRAY(" ", digest, digestLen); + + // Initialize multiple precision integers + mpiInit(&e); + mpiInit(&k); + // Initialize EC point + ecInit(&C); + + // Step 1: Compute hash (h) of the message (passed as input) */ + + // Step 2: Compute the integer a, the binary representation of which is the vector h, and determine e = a (mod q) + // Let N be the bit length of q + n = mpiGetBitLength(¶ms->q); + // Compute N = MIN(N, outlen) + n = MIN(n, digestLen * 8); + // Convert the digest to a multiple precision integer ( h(M) -> a ) + MPI_CHECK(mpiReadRaw(&e, digest, (n + 7) / 8)); + // Keep the leftmost N bits of the hash value + if ((n % 8) != 0) + MPI_CHECK(mpiShiftRight(&e, 8 - (n % 8))); + // Compute e = a (mod q), if e = 0, to e = 1 + MPI_CHECK(mpiMod(&e, &e, ¶ms->q)); + if (!mpiCompInt(&e, 0)) + MPI_CHECK(mpiSetValue(&e, 1)); + // Debug message + TRACE_DEBUG(" e:\r\n"); + TRACE_DEBUG_MPI(" ", &e); + do { + do { + // Step 3: Generate a random number k such as 0 < k < q + MPI_CHECK(mpiRandRange(&k, ¶ms->q, prngAlgo, prngContext)); + // Debug message + TRACE_DEBUG(" k:\r\n"); + TRACE_DEBUG_MPI(" ", &k); + // Step 4: Compute the point of the elliptic curve C = kP and determine r = Xc (mod q), where – Xc is the coordinate of point C. If r = 0, then go back to step 3. + EC_CHECK(ecrdsaGenerateSignatureStep4(params, &k, &C, signature)); + // Debug message + TRACE_DEBUG(" r:\r\n"); + TRACE_DEBUG_MPI(" ", &signature->r); + } while (!mpiCompInt(&signature->r, 0)); + // Step 5: Compute the value of s ≡ (rd + ke)(mod q). If s = 0, then go back to step 3. + EC_CHECK(ecrdsaGenerateSignatureStep5(&privateKey->d, &e, &k, ¶ms->q, signature)); + TRACE_DEBUG("%d\n", mpiGetLength(&signature->s)); + // Debug message + TRACE_DEBUG(" s:\r\n"); + TRACE_DEBUG_MPI(" ", &signature->s); + } while (!mpiCompInt(&signature->s, 0)); + // Dump ECRDSA signature + TRACE_DEBUG(" r:\r\n"); + TRACE_DEBUG_MPI(" ", &signature->r); + TRACE_DEBUG(" s:\r\n"); + TRACE_DEBUG_MPI(" ", &signature->s); +end: + // Release multiple precision integers + mpiFree(&e); + mpiFree(&k); + // Release EC point + ecFree(&C); + // Clean up side effects if necessary + if(error) { + // Release (R, S) integer pair + mpiFree(&signature->r); + mpiFree(&signature->s); + } + // Return status code + return error; +} + + +/** + * @brief ECRDSA signature verification + * @param[in] params EC domain parameters + * @param[in] publicKey Signer's EC public key + * @param[in] digest Digest of the message whose signature is to be verified + * @param[in] digestLen Length in octets of the digest + * @param[in] signature (R, S) integer pair + * @return Error code + **/ + +__weak_func error_t ecrdsaVerifySignature(const EcDomainParameters *params, + const EcPublicKey *publicKey, const uint8_t *digest, size_t digestLen, + const EcrdsaSignature *signature) +{ + error_t error; + uint_t n; + Mpi e; + + //Check parameters + if(params == NULL || publicKey == NULL || digest == NULL || signature == NULL) + return ERROR_INVALID_PARAMETER; + + //Debug message + TRACE_DEBUG("ECRDSA signature verification...\r\n"); + TRACE_DEBUG(" public key X:\r\n"); + TRACE_DEBUG_MPI(" ", &publicKey->q.x); + TRACE_DEBUG(" public key Y:\r\n"); + TRACE_DEBUG_MPI(" ", &publicKey->q.y); + TRACE_DEBUG(" digest:\r\n"); + TRACE_DEBUG_ARRAY(" ", digest, digestLen); + TRACE_DEBUG(" r:\r\n"); + TRACE_DEBUG_MPI(" ", &signature->r); + TRACE_DEBUG(" s:\r\n"); + TRACE_DEBUG_MPI(" ", &signature->s); + + //The verifier shall check that 0 < r < q, if the condition is violated, the signature shall be rejected as invalid + if(mpiCompInt(&signature->r, 0) <= 0 || mpiComp(&signature->r, ¶ms->q) >= 0) + return ERROR_INVALID_SIGNATURE; + + //The verifier shall check that 0 < s < q, if the condition is violated, the signature shall be rejected as invalid + if(mpiCompInt(&signature->s, 0) <= 0 || mpiComp(&signature->s, ¶ms->q) >= 0) + return ERROR_INVALID_SIGNATURE; + + //Initialize multiple precision integers + mpiInit(&e); + + //Let N be the bit length of q + n = mpiGetBitLength(¶ms->q); + //Compute N = MIN(N, outlen) + n = MIN(n, digestLen * 8); + //Convert the digest to a multiple precision integer + MPI_CHECK(mpiReadRaw(&e, digest, (n + 7) / 8)); + //Keep the leftmost N bits of the hash value + if((n % 8) != 0) + MPI_CHECK(mpiShiftRight(&e, 8 - (n % 8))); + // Steps 4-7 + MPI_CHECK(ecrdsaVerifySignatureFinal(params, &publicKey->q, &e, (EcrdsaSignature *)signature)); +end: + //Release multiple precision integers + mpiFree(&e); + //Return status code + return error; +} + +#if (ECRDSA_TEST_SUPPORT == ENABLED) +#define p_RAW_1 "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x31" +#define a_RAW_1 "\x07" +#define b_RAW_1 "\x5F\xBF\xF4\x98\xAA\x93\x8C\xE7\x39\xB8\xE0\x22\xFB\xAF\xEF\x40\x56\x3F\x6E\x6A\x34\x72\xFC\x2A\x51\x4C\x0C\xE9\xDA\xE2\x3B\x7E" +#define q_RAW_1 "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x50\xFE\x8A\x18\x92\x97\x61\x54\xC5\x9C\xFC\x19\x3A\xCC\xF5\xB3" +#define GX_RAW_1 "\x02" +#define GY_RAW_1 "\x08\xE2\xA8\xA0\xE6\x51\x47\xD4\xBD\x63\x16\x03\x0E\x16\xD1\x9C\x85\xC9\x7F\x0A\x9C\xA2\x67\x12\x2B\x96\xAB\xBC\xEA\x7E\x8F\xC8" +#define k_RAW_1 "\x77\x10\x5C\x9B\x20\xBC\xD3\x12\x28\x23\xC8\xCF\x6F\xCC\x7B\x95\x6D\xE3\x38\x14\xE9\x5B\x7F\xE6\x4F\xED\x92\x45\x94\xDC\xEA\xB3" +#define e_RAW_1 "\x2D\xFB\xC1\xB3\x72\xD8\x9A\x11\x88\xC0\x9C\x52\xE0\xEE\xC6\x1F\xCE\x52\x03\x2A\xB1\x02\x2E\x8E\x67\xEC\xE6\x67\x2B\x04\x3E\xE5" +#define d_RAW_1 "\x7A\x92\x9A\xDE\x78\x9B\xB9\xBE\x10\xED\x35\x9D\xD3\x9A\x72\xC1\x1B\x60\x96\x1F\x49\x39\x7E\xEE\x1D\x19\xCE\x98\x91\xEC\x3B\x28" +#define r_RAW_1 "\x41\xAA\x28\xD2\xF1\xAB\x14\x82\x80\xCD\x9E\xD5\x6F\xED\xA4\x19\x74\x05\x35\x54\xA4\x27\x67\xB8\x3A\xD0\x43\xFD\x39\xDC\x04\x93" +#define s_RAW_1 "\x01\x45\x6C\x64\xBA\x46\x42\xA1\x65\x3C\x23\x5A\x98\xA6\x02\x49\xBC\xD6\xD3\xF7\x46\xB6\x31\xDF\x92\x80\x14\xF6\xC5\xBF\x9C\x40" +#define QX_RAW_1 "\x7F\x2B\x49\xE2\x70\xDB\x6D\x90\xD8\x59\x5B\xEC\x45\x8B\x50\xC5\x85\x85\xBA\x1D\x4E\x9B\x78\x8F\x66\x89\xDB\xD8\xE5\x6F\xD8\x0B" +#define QY_RAW_1 "\x26\xF1\xB4\x89\xD6\x70\x1D\xD1\x85\xC8\x41\x3A\x97\x7B\x3C\xBB\xAF\x64\xD1\xC5\x93\xD2\x66\x27\xDF\xFB\x10\x1A\x87\xFF\x77\xDA" + +#define p_RAW_2 "\x45\x31\xAC\xD1\xFE\x00\x23\xC7\x55\x0D\x26\x7B\x6B\x2F\xEE\x80\x92\x2B\x14\xB2\xFF\xB9\x0F\x04\xD4\xEB\x7C\x09\xB5\xD2\xD1\x5D\xF1\xD8\x52\x74\x1A\xF4\x70\x4A\x04\x58\x04\x7E\x80\xE4\x54\x6D\x35\xB8\x33\x6F\xAC\x22\x4D\xD8\x16\x64\xBB\xF5\x28\xBE\x63\x73" +#define a_RAW_2 "\x07" +#define b_RAW_2 "\x1C\xFF\x08\x06\xA3\x11\x16\xDA\x29\xD8\xCF\xA5\x4E\x57\xEB\x74\x8B\xC5\xF3\x77\xE4\x94\x00\xFD\xD7\x88\xB6\x49\xEC\xA1\xAC\x43\x61\x83\x40\x13\xB2\xAD\x73\x22\x48\x0A\x89\xCA\x58\xE0\xCF\x74\xBC\x9E\x54\x0C\x2A\xDD\x68\x97\xFA\xD0\xA3\x08\x4F\x30\x2A\xDC" +#define q_RAW_2 "\x45\x31\xAC\xD1\xFE\x00\x23\xC7\x55\x0D\x26\x7B\x6B\x2F\xEE\x80\x92\x2B\x14\xB2\xFF\xB9\x0F\x04\xD4\xEB\x7C\x09\xB5\xD2\xD1\x5D\xA8\x2F\x2D\x7E\xCB\x1D\xBA\xC7\x19\x90\x5C\x5E\xEC\xC4\x23\xF1\xD8\x6E\x25\xED\xBE\x23\xC5\x95\xD6\x44\xAA\xF1\x87\xE6\xE6\xDF" +#define GX_RAW_2 "\x24\xD1\x9C\xC6\x45\x72\xEE\x30\xF3\x96\xBF\x6E\xBB\xFD\x7A\x6C\x52\x13\xB3\xB3\xD7\x05\x7C\xC8\x25\xF9\x10\x93\xA6\x8C\xD7\x62\xFD\x60\x61\x12\x62\xCD\x83\x8D\xC6\xB6\x0A\xA7\xEE\xE8\x04\xE2\x8B\xC8\x49\x97\x7F\xAC\x33\xB4\xB5\x30\xF1\xB1\x20\x24\x8A\x9A" +#define GY_RAW_2 "\x2B\xB3\x12\xA4\x3B\xD2\xCE\x6E\x0D\x02\x06\x13\xC8\x57\xAC\xDD\xCF\xBF\x06\x1E\x91\xE5\xF2\xC3\xF3\x24\x47\xC2\x59\xF3\x9B\x2C\x83\xAB\x15\x6D\x77\xF1\x49\x6B\xF7\xEB\x33\x51\xE1\xEE\x4E\x43\xDC\x1A\x18\xB9\x1B\x24\x64\x0B\x6D\xBB\x92\xCB\x1A\xDD\x37\x1E" +#define k_RAW_2 "\x03\x59\xE7\xF4\xB1\x41\x0F\xEA\xCC\x57\x04\x56\xC6\x80\x14\x96\x94\x63\x12\x12\x0B\x39\xD0\x19\xD4\x55\x98\x6E\x36\x4F\x36\x58\x86\x74\x8E\xD7\xA4\x4B\x3E\x79\x44\x34\x00\x60\x11\x84\x22\x86\x21\x22\x73\xA6\xD1\x4C\xF7\x0E\xA3\xAF\x71\xBB\x1A\xE6\x79\xF1" +#define e_RAW_2 "\x37\x54\xF3\xCF\xAC\xC9\xE0\x61\x5C\x4F\x4A\x7C\x4D\x8D\xAB\x53\x1B\x09\xB6\xF9\xC1\x70\xC5\x33\xA7\x1D\x14\x70\x35\xB0\xC5\x91\x71\x84\xEE\x53\x65\x93\xF4\x41\x43\x39\x97\x6C\x64\x7C\x5D\x5A\x40\x7A\xDE\xDB\x1D\x56\x0C\x4F\xC6\x77\x7D\x29\x72\x07\x5B\x8C" +#define d_RAW_2 "\x0B\xA6\x04\x8A\xAD\xAE\x24\x1B\xA4\x09\x36\xD4\x77\x56\xD7\xC9\x30\x91\xA0\xE8\x51\x46\x69\x70\x0E\xE7\x50\x8E\x50\x8B\x10\x20\x72\xE8\x12\x3B\x22\x00\xA0\x56\x33\x22\xDA\xD2\x82\x7E\x27\x14\xA2\x63\x6B\x7B\xFD\x18\xAA\xDF\xC6\x29\x67\x82\x1F\xA1\x8D\xD4" +#define r_RAW_2 "\x2F\x86\xFA\x60\xA0\x81\x09\x1A\x23\xDD\x79\x5E\x1E\x3C\x68\x9E\xE5\x12\xA3\xC8\x2E\xE0\xDC\xC2\x64\x3C\x78\xEE\xA8\xFC\xAC\xD3\x54\x92\x55\x84\x86\xB2\x0F\x1C\x9E\xC1\x97\xC9\x06\x99\x85\x02\x60\xC9\x3B\xCB\xCD\x9C\x5C\x33\x17\xE1\x93\x44\xE1\x73\xAE\x36" +#define s_RAW_2 "\x10\x81\xB3\x94\x69\x6F\xFE\x8E\x65\x85\xE7\xA9\x36\x2D\x26\xB6\x32\x5F\x56\x77\x8A\xAD\xBC\x08\x1C\x0B\xFB\xE9\x33\xD5\x2F\xF5\x82\x3C\xE2\x88\xE8\xC4\xF3\x62\x52\x60\x80\xDF\x7F\x70\xCE\x40\x6A\x6E\xEB\x1F\x56\x91\x9C\xB9\x2A\x98\x53\xBD\xE7\x3E\x5B\x4A" +#define QX_RAW_2 "\x11\x5D\xC5\xBC\x96\x76\x0C\x7B\x48\x59\x8D\x8A\xB9\xE7\x40\xD4\xC4\xA8\x5A\x65\xBE\x33\xC1\x81\x5B\x5C\x32\x0C\x85\x46\x21\xDD\x5A\x51\x58\x56\xD1\x33\x14\xAF\x69\xBC\x5B\x92\x4C\x8B\x4D\xDF\xF7\x5C\x45\x41\x5C\x1D\x9D\xD9\xDD\x33\x61\x2C\xD5\x30\xEF\xE1" +#define QY_RAW_2 "\x37\xC7\xC9\x0C\xD4\x0B\x0F\x56\x21\xDC\x3A\xC1\xB7\x51\xCF\xA0\xE2\x63\x4F\xA0\x50\x3B\x3D\x52\x63\x9F\x5D\x7F\xB7\x2A\xFD\x61\xEA\x19\x94\x41\xD9\x43\xFF\xE7\xF0\xC7\x0A\x27\x59\xA3\xCD\xB8\x4C\x11\x4E\x1F\x93\x39\xFD\xF2\x7F\x35\xEC\xA9\x36\x77\xBE\xEC" + +struct Param { + uint8_t *data; + uint_t size; +}; + +struct Params { + struct Param p; + struct Param a; + struct Param b; + struct Param q; + struct Param gx; + struct Param gy; + struct Param k; + struct Param e; + struct Param d; + struct Param r; + struct Param s; + struct Param qx; + struct Param qy; +}; + +static struct Params test[2] = { + { + p_RAW_1, sizeof(p_RAW_1) - 1, + a_RAW_1, sizeof(a_RAW_1) - 1, + b_RAW_1, sizeof(b_RAW_1) - 1, + q_RAW_1, sizeof(q_RAW_1) - 1, + GX_RAW_1, sizeof(GX_RAW_1) - 1, + GY_RAW_1, sizeof(GY_RAW_1) - 1, + k_RAW_1, sizeof(k_RAW_1) - 1, + e_RAW_1, sizeof(e_RAW_1) - 1, + d_RAW_1, sizeof(d_RAW_1) - 1, + r_RAW_1, sizeof(r_RAW_1) - 1, + s_RAW_1, sizeof(s_RAW_1) - 1, + QX_RAW_1, sizeof(QX_RAW_1) - 1, + QY_RAW_1, sizeof(QY_RAW_1) - 1, + }, + { + p_RAW_2, sizeof(p_RAW_2) - 1, + a_RAW_2, sizeof(a_RAW_2) - 1, + b_RAW_2, sizeof(b_RAW_2) - 1, + q_RAW_2, sizeof(q_RAW_2) - 1, + GX_RAW_2, sizeof(GX_RAW_2) - 1, + GY_RAW_2, sizeof(GY_RAW_2) - 1, + k_RAW_2, sizeof(k_RAW_2) - 1, + e_RAW_2, sizeof(e_RAW_2) - 1, + d_RAW_2, sizeof(d_RAW_2) - 1, + r_RAW_2, sizeof(r_RAW_2) - 1, + s_RAW_2, sizeof(s_RAW_2) - 1, + QX_RAW_2, sizeof(QX_RAW_2) - 1, + QY_RAW_2, sizeof(QY_RAW_2) - 1, + } +}; + +__weak_func error_t ecrdsaTest(void) +{ + error_t error; + EcDomainParameters params; + Mpi e; + Mpi k; + Mpi r; // test value + Mpi s; // test value + Mpi d; // private key + Mpi v; + Mpi z1; + Mpi z2; + EcPoint Q; // public key + EcPoint C; + EcrdsaSignature signature; + + ecInitDomainParameters(¶ms); + params.h = 1; + params.mod = NULL; + mpiInit(&e); + mpiInit(&k); + mpiInit(&r); + mpiInit(&s); + mpiInit(&d); + mpiInit(&v); + mpiInit(&z1); + mpiInit(&z2); + ecInit(&Q); + ecInit(&C); + ecrdsaInitSignature(&signature); + + for (int i = 0; i < 2; ++i) { + + mpiReadRaw(¶ms.p, test[i].p.data, test[i].p.size); + mpiReadRaw(¶ms.a, test[i].a.data, test[i].a.size); + mpiReadRaw(¶ms.b, test[i].b.data, test[i].b.size); + mpiReadRaw(¶ms.q, test[i].q.data, test[i].q.size); + mpiReadRaw(¶ms.g.x, test[i].gx.data, test[i].gx.size); + mpiReadRaw(¶ms.g.y, test[i].gy.data, test[i].gy.size); + mpiSetValue(¶ms.g.z, 1); + mpiReadRaw(&k, test[i].k.data, test[i].k.size); + mpiReadRaw(&e, test[i].e.data, test[i].e.size); + mpiReadRaw(&d, test[i].d.data, test[i].d.size); + + mpiReadRaw(&r, test[i].r.data, test[i].r.size); + mpiReadRaw(&s, test[i].s.data, test[i].s.size); + + mpiReadRaw(&Q.x, test[i].qx.data, test[i].qx.size); + mpiReadRaw(&Q.y, test[i].qy.data, test[i].qy.size); + mpiSetValue(&Q.z, 1); + + TRACE_INFO("\r\nTest %d:\r\n", i + 1); + TRACE_INFO("************\r\n"); + TRACE_INFO(" In:\r\n"); + + TRACE_INFO(" p:\r\n"); + TRACE_INFO_MPI(" ", ¶ms.p); + TRACE_INFO(" a:\r\n"); + TRACE_INFO_MPI(" ", ¶ms.a); + TRACE_INFO(" b:\r\n"); + TRACE_INFO_MPI(" ", ¶ms.b); + TRACE_INFO(" q:\r\n"); + TRACE_INFO_MPI(" ", ¶ms.q); + TRACE_INFO(" Gx:\r\n"); + TRACE_INFO_MPI(" ", ¶ms.g.x); + TRACE_INFO(" Gy:\r\n"); + TRACE_INFO_MPI(" ", ¶ms.g.y); + TRACE_INFO(" k:\r\n"); + TRACE_INFO_MPI(" ", &k); + TRACE_INFO(" e:\r\n"); + TRACE_INFO_MPI(" ", &e); + TRACE_INFO(" d:\r\n"); + TRACE_INFO_MPI(" ", &d); + + + /* Sign test */ + // Steps 1-3: Predefined + // Step 1: Compute hash (h) of the message (passed as input) */ + // Step 2: Compute the integer a, the binary representation of which is the vector h, and determine e = a (mod q) + // Step 3: Define k such as 0 < k < q, + + // Step 4: Compute the point of the elliptic curve C = kP and determine r = Xc (mod q), where – Xc is the coordinate of point C. If r = 0, then go back to step 3. + EC_CHECK(ecrdsaGenerateSignatureStep4(¶ms, &k, &C, &signature)); + // Step 5: Compute the value of s ≡ (rd + ke)(mod q). If s = 0, then go back to step 3. + EC_CHECK(ecrdsaGenerateSignatureStep5(&d, &e, &k, ¶ms.q, &signature)); + + TRACE_INFO(" Out:\r\n"); + // Dump ECRDSA signature + TRACE_INFO(" r:\r\n"); + TRACE_INFO_MPI(" ", &signature.r); + TRACE_INFO(" s:\r\n"); + TRACE_INFO_MPI(" ", &signature.s); + + TRACE_INFO("Test %d sign result: %s\r\n", i + 1, (!mpiComp(&r, &signature.r) || !mpiComp(&s, &signature.s)) ? "OK" : "ERROR"); + + + /* Verify test */ + MPI_CHECK(ecrdsaVerifySignatureFinal(¶ms, &Q, &e, &signature)); + TRACE_INFO("Test %d veryfy result: %s\r\n", i + 1, error == NO_ERROR ? "OK" : "ERROR"); + } +end: + // Release multiple precision integers + mpiFree(&e); + mpiFree(&k); + mpiFree(&r); + mpiFree(&s); + mpiFree(&d); + mpiFree(&v); + mpiFree(&z1); + mpiFree(&z2); + // Release EC point + ecFree(&C); + ecFree(&Q); + + // Release (R, S) integer pair + mpiFree(&signature.r); + mpiFree(&signature.s); + + //Release previously allocated resources + ecFreeDomainParameters(¶ms); + + // Return status code + return error; +} + +#endif + +#endif diff --git a/ecc/ecrdsa.h b/ecc/ecrdsa.h new file mode 100644 index 00000000..3a865ad6 --- /dev/null +++ b/ecc/ecrdsa.h @@ -0,0 +1,102 @@ +/** + * @file ecrdsa.h + * @brief ECRDSA (Elliptic Curve Russian Digital Signature Algorithm) + * + * Elliptic Curve (Russian) Digital Signature Algorithm for Cryptographic API + * + * Copyright (c) 2024 Valery Novikov + * + * References: + * GOST 34.10-2018, GOST R 34.10-2012, RFC 7091, ISO/IEC 14888-3:2018. + * + * Historical references: + * GOST R 34.10-2001, RFC 4357, ISO/IEC 14888-3:2006/Amd 1:2010. + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Valery Novikov + * @version 2.4.0 + **/ + +#ifndef _ECRDSA_H +#define _ECRDSA_H + +//Dependencies +#include "core/crypto.h" +#include "ecc/ec.h" + +//C++ guard +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief ECRDSA signature + **/ + +typedef struct +{ + Mpi r; + Mpi s; +} EcrdsaSignature; + + +//ECRDSA related constants +extern const uint8_t ECDSA_WITH_SHA1_OID[7]; +extern const uint8_t ECDSA_WITH_SHA224_OID[8]; +extern const uint8_t ECDSA_WITH_SHA256_OID[8]; +extern const uint8_t ECDSA_WITH_SHA384_OID[8]; +extern const uint8_t ECDSA_WITH_SHA512_OID[8]; +extern const uint8_t ECDSA_WITH_SHA3_224_OID[9]; +extern const uint8_t ECDSA_WITH_SHA3_256_OID[9]; +extern const uint8_t ECDSA_WITH_SHA3_384_OID[9]; +extern const uint8_t ECDSA_WITH_SHA3_512_OID[9]; + +//ECRDSA related functions +void ecrdsaInitSignature(EcrdsaSignature *signature); +void ecrdsaFreeSignature(EcrdsaSignature *signature); + +error_t ecrdsaWriteSignature(const EcrdsaSignature *signature, uint8_t *data, + size_t *length); + +error_t ecrdsaReadSignature(const uint8_t *data, size_t length, EcrdsaSignature *signature); + +error_t ecrdsaGenerateSignature(const PrngAlgo *prngAlgo, void *prngContext, + const EcDomainParameters *params, const EcPrivateKey *privateKey, + const uint8_t *digest, size_t digestLen, EcrdsaSignature *signature); + +error_t ecrdsaVerifySignature(const EcDomainParameters *params, + const EcPublicKey *publicKey, const uint8_t *digest, size_t digestLen, + const EcrdsaSignature *signature); + +#if (ECRDSA_TEST_SUPPORT == ENABLED) +error_t ecrdsaTest(void); +#endif + +//C++ guard +#ifdef __cplusplus +} +#endif + +#endif diff --git a/pkc/sign_algorithms.h b/pkc/sign_algorithms.h index a55e62ef..b9734923 100644 --- a/pkc/sign_algorithms.h +++ b/pkc/sign_algorithms.h @@ -49,6 +49,11 @@ #include "ecc/ecdsa.h" #endif +//ECRDSA support? +#if (ECRDSA_SUPPORT == ENABLED) +#include "ecc/ecrdsa.h" +#endif + //SM2 support? #if (SM2_SUPPORT == ENABLED) #include "ecc/sm2.h" From f3c74f39e70f74b343862638e671b55c2a7c65b5 Mon Sep 17 00:00:00 2001 From: Novikov Valerii Date: Mon, 19 Feb 2024 14:00:48 +0500 Subject: [PATCH 3/8] Fix streeebog OIDs --- hash/streebog.c | 4 ++-- hash/streebog.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/hash/streebog.c b/hash/streebog.c index 62c403ab..683b15bb 100644 --- a/hash/streebog.c +++ b/hash/streebog.c @@ -45,7 +45,7 @@ #if (STREEBOG256_SUPPORT == ENABLED) //Streebog-256 object identifier (1.2.643.7.1.1.2.2) */ /* Generate by https://misc.daniel-marschall.de/asn.1/oid-converter/online.php */ -const uint8_t STREEBOG256_OID[10] = { 0x06, 0x08, 0x2A, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x02 }; +const uint8_t STREEBOG256_OID[8] = { 0x2A, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x02 }; //Common interface for hash algorithms const HashAlgo streebog256HashAlgo = @@ -68,7 +68,7 @@ const HashAlgo streebog256HashAlgo = #if (STREEBOG512_SUPPORT == ENABLED) //Streebog-256 object identifier (1.2.643.7.1.1.2.3) */ /* Generate by https://misc.daniel-marschall.de/asn.1/oid-converter/online.php */ -const uint8_t STREEBOG512_OID[10] = { 0x06, 0x08, 0x2A, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x03 }; +const uint8_t STREEBOG512_OID[8] = { 0x2A, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x03 }; //Common interface for hash algorithms const HashAlgo streebog512HashAlgo = diff --git a/hash/streebog.h b/hash/streebog.h index c60954f6..6077d843 100644 --- a/hash/streebog.h +++ b/hash/streebog.h @@ -101,14 +101,14 @@ typedef struct //Streebog related constants #if (STREEBOG256_SUPPORT == ENABLED) -extern const uint8_t STREEBOG256_OID[10]; +extern const uint8_t STREEBOG256_OID[8]; extern const HashAlgo streebog256HashAlgo; error_t streebog256Compute(const void *data, size_t length, uint8_t *digest); void streebog256Init(StreebogContext *context); #endif #if (STREEBOG512_SUPPORT == ENABLED) -extern const uint8_t STREEBOG512_OID[10]; +extern const uint8_t STREEBOG512_OID[8]; extern const HashAlgo streebog512HashAlgo; error_t streebog512Compute(const void *data, size_t length, uint8_t *digest); From 077e0a1771b9993fd6720a9629f0e92c84e15841 Mon Sep 17 00:00:00 2001 From: Novikov Valerii Date: Tue, 20 Feb 2024 12:04:06 +0500 Subject: [PATCH 4/8] Added Russian Elliptic curves tc26-gost-3410-12-512-paramSetA & tc26-gost-3410-12-512-paramSetB --- ecc/ec_curves.c | 5299 ++++++++++++++++++++++++----------------------- ecc/ec_curves.h | 25 +- 2 files changed, 2741 insertions(+), 2583 deletions(-) diff --git a/ecc/ec_curves.c b/ecc/ec_curves.c index 26cc93a8..42ea0927 100644 --- a/ecc/ec_curves.c +++ b/ecc/ec_curves.c @@ -1,2582 +1,2717 @@ -/** - * @file ec_curves.c - * @brief Elliptic curves - * - * @section License - * - * SPDX-License-Identifier: GPL-2.0-or-later - * - * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. - * - * This file is part of CycloneCRYPTO Open. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * @author Oryx Embedded SARL (www.oryx-embedded.com) - * @version 2.4.0 - **/ - -//Switch to the appropriate trace level -#define TRACE_LEVEL CRYPTO_TRACE_LEVEL - -//Dependencies -#include "core/crypto.h" -#include "ecc/ec_curves.h" -#include "encoding/oid.h" -#include "debug.h" - -//Check crypto library configuration -#if (EC_SUPPORT == ENABLED) - -//Macro definition -#define CLEAR_WORD32(a, i, n) osMemset((a)->data + i, 0, n * MPI_INT_SIZE); -#define COPY_WORD32(a, i, b, j, n) osMemcpy((a)->data + i, (b)->data + j, n * MPI_INT_SIZE); - -//secp112r1 OID (1.3.132.0.6) -const uint8_t SECP112R1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x06}; -//secp112r2 OID (1.3.132.0.7) -const uint8_t SECP112R2_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x07}; -//secp128r1 OID (1.3.132.0.28) -const uint8_t SECP128R1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x1C}; -//secp128r2 OID (1.3.132.0.29) -const uint8_t SECP128R2_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x1D}; -//secp160k1 OID (1.3.132.0.9) -const uint8_t SECP160K1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x09}; -//secp160r1 OID (1.3.132.0.8) -const uint8_t SECP160R1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x08}; -//secp160r2 OID (1.3.132.0.30) -const uint8_t SECP160R2_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x1E}; -//secp192k1 OID (1.3.132.0.31) -const uint8_t SECP192K1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x1F}; -//secp192r1 OID (1.2.840.10045.3.1.1) -const uint8_t SECP192R1_OID[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x01}; -//secp224k1 OID (1.3.132.0.32) -const uint8_t SECP224K1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x20}; -//secp224r1 OID (1.3.132.0.33) -const uint8_t SECP224R1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x21}; -//secp256k1 OID (1.3.132.0.10) -const uint8_t SECP256K1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x0A}; -//secp256r1 OID (1.2.840.10045.3.1.7) -const uint8_t SECP256R1_OID[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}; -//secp384r1 OID (1.3.132.0.34) -const uint8_t SECP384R1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x22}; -//secp521r1 OID (1.3.132.0.35) -const uint8_t SECP521R1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x23}; -//brainpoolP160r1 OID (1.3.36.3.3.2.8.1.1.1) -const uint8_t BRAINPOOLP160R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x01}; -//brainpoolP192r1 OID (1.3.36.3.3.2.8.1.1.3) -const uint8_t BRAINPOOLP192R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x03}; -//brainpoolP224r1 OID (1.3.36.3.3.2.8.1.1.5) -const uint8_t BRAINPOOLP224R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x05}; -//brainpoolP256r1 OID (1.3.36.3.3.2.8.1.1.7) -const uint8_t BRAINPOOLP256R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}; -//brainpoolP320r1 OID (1.3.36.3.3.2.8.1.1.9) -const uint8_t BRAINPOOLP320R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x09}; -//brainpoolP384r1 OID (1.3.36.3.3.2.8.1.1.11) -const uint8_t BRAINPOOLP384R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}; -//brainpoolP512r1 OID (1.3.36.3.3.2.8.1.1.13) -const uint8_t BRAINPOOLP512R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}; -//SM2 OID (1.2.156.10197.1.301) -const uint8_t SM2_OID[8] = {0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x82, 0x2D}; -//X25519 OID (1.3.101.110) -const uint8_t X25519_OID[3] = {0x2B, 0x65, 0x6E}; -//X448 OID (1.3.101.111) -const uint8_t X448_OID[3] = {0x2B, 0x65, 0x6F}; -//Ed25519 OID (1.3.101.112) -const uint8_t ED25519_OID[3] = {0x2B, 0x65, 0x70}; -//Ed448 OID (1.3.101.113) -const uint8_t ED448_OID[3] = {0x2B, 0x65, 0x71}; - - -#if (SECP112R1_SUPPORT == ENABLED) - -/** - * @brief secp112r1 elliptic curve - **/ - -const EcCurveInfo secp112r1Curve = -{ - //Curve name - "secp112r1", - //Object identifier - SECP112R1_OID, - sizeof(SECP112R1_OID), - //Curve type - EC_CURVE_TYPE_SECP_R1, - //Prime modulus p - {0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x66, 0x80, 0x76, 0xBE, 0xAD, 0x20, 0x8B}, - 14, - //Curve parameter a - {0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x66, 0x80, 0x76, 0xBE, 0xAD, 0x20, 0x88}, - 14, - //Curve parameter b - {0x65, 0x9E, 0xF8, 0xBA, 0x04, 0x39, 0x16, 0xEE, 0xDE, 0x89, 0x11, 0x70, 0x2B, 0x22}, - 14, - //x-coordinate of the base point G - {0x09, 0x48, 0x72, 0x39, 0x99, 0x5A, 0x5E, 0xE7, 0x6B, 0x55, 0xF9, 0xC2, 0xF0, 0x98}, - 14, - //y-coordinate of the base point G - {0xA8, 0x9C, 0xE5, 0xAF, 0x87, 0x24, 0xC0, 0xA2, 0x3E, 0x0E, 0x0F, 0xF7, 0x75, 0x00}, - 14, - //Base point order q - {0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x76, 0x28, 0xDF, 0xAC, 0x65, 0x61, 0xC5}, - 14, - //Cofactor - 1, - //Fast modular reduction - NULL -}; - -#endif -#if (SECP112R2_SUPPORT == ENABLED) - -/** - * @brief secp112r2 elliptic curve - **/ - -const EcCurveInfo secp112r2Curve = -{ - //Curve name - "secp112r2", - //Object identifier - SECP112R2_OID, - sizeof(SECP112R2_OID), - //Curve type - EC_CURVE_TYPE_SECP_R2, - //Prime modulus p - {0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x66, 0x80, 0x76, 0xBE, 0xAD, 0x20, 0x8B}, - 14, - //Curve parameter a - {0x61, 0x27, 0xC2, 0x4C, 0x05, 0xF3, 0x8A, 0x0A, 0xAA, 0xF6, 0x5C, 0x0E, 0xF0, 0x2C}, - 14, - //Curve parameter b - {0x51, 0xDE, 0xF1, 0x81, 0x5D, 0xB5, 0xED, 0x74, 0xFC, 0xC3, 0x4C, 0x85, 0xD7, 0x09}, - 14, - //x-coordinate of the base point G - {0x4B, 0xA3, 0x0A, 0xB5, 0xE8, 0x92, 0xB4, 0xE1, 0x64, 0x9D, 0xD0, 0x92, 0x86, 0x43}, - 14, - //y-coordinate of the base point G - {0xAD, 0xCD, 0x46, 0xF5, 0x88, 0x2E, 0x37, 0x47, 0xDE, 0xF3, 0x6E, 0x95, 0x6E, 0x97}, - 14, - //Base point order q - {0x36, 0xDF, 0x0A, 0xAF, 0xD8, 0xB8, 0xD7, 0x59, 0x7C, 0xA1, 0x05, 0x20, 0xD0, 0x4B}, - 14, - //Cofactor - 4, - //Fast modular reduction - NULL -}; - -#endif -#if (SECP128R1_SUPPORT == ENABLED) - -/** - * @brief secp128r1 elliptic curve - **/ - -const EcCurveInfo secp128r1Curve = -{ - //Curve name - "secp128r1", - //Object identifier - SECP128R1_OID, - sizeof(SECP128R1_OID), - //Curve type - EC_CURVE_TYPE_SECP_R1, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - 16, - //Curve parameter a - {0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}, - 16, - //Curve parameter b - {0xE8, 0x75, 0x79, 0xC1, 0x10, 0x79, 0xF4, 0x3D, 0xD8, 0x24, 0x99, 0x3C, 0x2C, 0xEE, 0x5E, 0xD3}, - 16, - //x-coordinate of the base point G - {0x16, 0x1F, 0xF7, 0x52, 0x8B, 0x89, 0x9B, 0x2D, 0x0C, 0x28, 0x60, 0x7C, 0xA5, 0x2C, 0x5B, 0x86}, - 16, - //y-coordinate of the base point G - {0xCF, 0x5A, 0xC8, 0x39, 0x5B, 0xAF, 0xEB, 0x13, 0xC0, 0x2D, 0xA2, 0x92, 0xDD, 0xED, 0x7A, 0x83}, - 16, - //Base point order q - {0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x75, 0xA3, 0x0D, 0x1B, 0x90, 0x38, 0xA1, 0x15}, - 16, - //Cofactor - 1, - //Fast modular reduction - secp128r1Mod -}; - -#endif -#if (SECP128R2_SUPPORT == ENABLED) - -/** - * @brief secp128r2 elliptic curve - **/ - -const EcCurveInfo secp128r2Curve = -{ - //Curve name - "secp128r2", - //Object identifier - SECP128R2_OID, - sizeof(SECP128R2_OID), - //Curve type - EC_CURVE_TYPE_SECP_R2, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - 16, - //Curve parameter a - {0xD6, 0x03, 0x19, 0x98, 0xD1, 0xB3, 0xBB, 0xFE, 0xBF, 0x59, 0xCC, 0x9B, 0xBF, 0xF9, 0xAE, 0xE1}, - 16, - //Curve parameter b - {0x5E, 0xEE, 0xFC, 0xA3, 0x80, 0xD0, 0x29, 0x19, 0xDC, 0x2C, 0x65, 0x58, 0xBB, 0x6D, 0x8A, 0x5D}, - 16, - //x-coordinate of the base point G - {0x7B, 0x6A, 0xA5, 0xD8, 0x5E, 0x57, 0x29, 0x83, 0xE6, 0xFB, 0x32, 0xA7, 0xCD, 0xEB, 0xC1, 0x40}, - 16, - //y-coordinate of the base point G - {0x27, 0xB6, 0x91, 0x6A, 0x89, 0x4D, 0x3A, 0xEE, 0x71, 0x06, 0xFE, 0x80, 0x5F, 0xC3, 0x4B, 0x44}, - 16, - //Base point order q - {0x3F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xBE, 0x00, 0x24, 0x72, 0x06, 0x13, 0xB5, 0xA3}, - 16, - //Cofactor - 4, - //Fast modular reduction - secp128r2Mod -}; - -#endif -#if (SECP160K1_SUPPORT == ENABLED) - -/** - * @brief secp160k1 elliptic curve - **/ - -const EcCurveInfo secp160k1Curve = -{ - //Curve name - "secp160k1", - //Object identifier - SECP160K1_OID, - sizeof(SECP160K1_OID), - //Curve type - EC_CURVE_TYPE_SECP_K1, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0xFF, 0xFF, 0xAC, 0x73}, - 20, - //Curve parameter a - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}, - 20, - //Curve parameter b - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x07}, - 20, - //x-coordinate of the base point G - {0x3B, 0x4C, 0x38, 0x2C, 0xE3, 0x7A, 0xA1, 0x92, 0xA4, 0x01, 0x9E, 0x76, 0x30, 0x36, 0xF4, 0xF5, - 0xDD, 0x4D, 0x7E, 0xBB}, - 20, - //y-coordinate of the base point G - {0x93, 0x8C, 0xF9, 0x35, 0x31, 0x8F, 0xDC, 0xED, 0x6B, 0xC2, 0x82, 0x86, 0x53, 0x17, 0x33, 0xC3, - 0xF0, 0x3C, 0x4F, 0xEE}, - 20, - //Base point order q - {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB8, 0xFA, 0x16, 0xDF, 0xAB, - 0x9A, 0xCA, 0x16, 0xB6, 0xB3}, - 21, - //Cofactor - 1, - //Fast modular reduction - secp160k1Mod -}; - -#endif -#if (SECP160R1_SUPPORT == ENABLED) - -/** - * @brief secp160r1 elliptic curve - **/ - -const EcCurveInfo secp160r1Curve = -{ - //Curve name - "secp160r1", - //Object identifier - SECP160R1_OID, - sizeof(SECP160R1_OID), - //Curve type - EC_CURVE_TYPE_SECP_R1, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x7F, 0xFF, 0xFF, 0xFF}, - 20, - //Curve parameter a - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x7F, 0xFF, 0xFF, 0xFC}, - 20, - //Curve parameter b - {0x1C, 0x97, 0xBE, 0xFC, 0x54, 0xBD, 0x7A, 0x8B, 0x65, 0xAC, 0xF8, 0x9F, 0x81, 0xD4, 0xD4, 0xAD, - 0xC5, 0x65, 0xFA, 0x45}, - 20, - //x-coordinate of the base point G - {0x4A, 0x96, 0xB5, 0x68, 0x8E, 0xF5, 0x73, 0x28, 0x46, 0x64, 0x69, 0x89, 0x68, 0xC3, 0x8B, 0xB9, - 0x13, 0xCB, 0xFC, 0x82}, - 20, - //y-coordinate of the base point G - {0x23, 0xA6, 0x28, 0x55, 0x31, 0x68, 0x94, 0x7D, 0x59, 0xDC, 0xC9, 0x12, 0x04, 0x23, 0x51, 0x37, - 0x7A, 0xC5, 0xFB, 0x32}, - 20, - //Base point order q - {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF4, 0xC8, 0xF9, 0x27, 0xAE, - 0xD3, 0xCA, 0x75, 0x22, 0x57}, - 21, - //Cofactor - 1, - //Fast modular reduction - secp160r1Mod -}; - -#endif -#if (SECP160R2_SUPPORT == ENABLED) - -/** - * @brief secp160r2 elliptic curve - **/ - -const EcCurveInfo secp160r2Curve = -{ - //Curve name - "secp160r2", - //Object identifier - SECP160R2_OID, - sizeof(SECP160R2_OID), - //Curve type - EC_CURVE_TYPE_SECP_R2, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0xFF, 0xFF, 0xAC, 0x73}, - 20, - //Curve parameter a - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0xFF, 0xFF, 0xAC, 0x70}, - 20, - //Curve parameter b - {0xB4, 0xE1, 0x34, 0xD3, 0xFB, 0x59, 0xEB, 0x8B, 0xAB, 0x57, 0x27, 0x49, 0x04, 0x66, 0x4D, 0x5A, - 0xF5, 0x03, 0x88, 0xBA}, - 20, - //x-coordinate of the base point G - {0x52, 0xDC, 0xB0, 0x34, 0x29, 0x3A, 0x11, 0x7E, 0x1F, 0x4F, 0xF1, 0x1B, 0x30, 0xF7, 0x19, 0x9D, - 0x31, 0x44, 0xCE, 0x6D}, - 20, - //y-coordinate of the base point G - {0xFE, 0xAF, 0xFE, 0xF2, 0xE3, 0x31, 0xF2, 0x96, 0xE0, 0x71, 0xFA, 0x0D, 0xF9, 0x98, 0x2C, 0xFE, - 0xA7, 0xD4, 0x3F, 0x2E}, - 20, - //Base point order q - {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x1E, 0xE7, 0x86, 0xA8, - 0x18, 0xF3, 0xA1, 0xA1, 0x6B}, - 21, - //Cofactor - 1, - //Fast modular reduction - secp160r2Mod -}; - -#endif -#if (SECP192K1_SUPPORT == ENABLED) - -/** - * @brief secp192k1 elliptic curve - **/ - -const EcCurveInfo secp192k1Curve = -{ - //Curve name - "secp192k1", - //Object identifier - SECP192K1_OID, - sizeof(SECP192K1_OID), - //Curve type - EC_CURVE_TYPE_SECP_K1, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEE, 0x37}, - 24, - //Curve parameter a - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - 24, - //Curve parameter b - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, - 24, - //x-coordinate of the base point G - {0xDB, 0x4F, 0xF1, 0x0E, 0xC0, 0x57, 0xE9, 0xAE, 0x26, 0xB0, 0x7D, 0x02, 0x80, 0xB7, 0xF4, 0x34, - 0x1D, 0xA5, 0xD1, 0xB1, 0xEA, 0xE0, 0x6C, 0x7D}, - 24, - //y-coordinate of the base point G - {0x9B, 0x2F, 0x2F, 0x6D, 0x9C, 0x56, 0x28, 0xA7, 0x84, 0x41, 0x63, 0xD0, 0x15, 0xBE, 0x86, 0x34, - 0x40, 0x82, 0xAA, 0x88, 0xD9, 0x5E, 0x2F, 0x9D}, - 24, - //Base point order q - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x26, 0xF2, 0xFC, 0x17, - 0x0F, 0x69, 0x46, 0x6A, 0x74, 0xDE, 0xFD, 0x8D}, - 24, - //Cofactor - 1, - //Fast modular reduction - secp192k1Mod -}; - -#endif -#if (SECP192R1_SUPPORT == ENABLED) - -/** - * @brief secp192r1 elliptic curve - **/ - -const EcCurveInfo secp192r1Curve = -{ - //Curve name - "secp192r1", - //Object identifier - SECP192R1_OID, - sizeof(SECP192R1_OID), - //Curve type - EC_CURVE_TYPE_SECP_R1, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - 24, - //Curve parameter a - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}, - 24, - //Curve parameter b - {0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7, 0x0F, 0xA7, 0xE9, 0xAB, 0x72, 0x24, 0x30, 0x49, - 0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1}, - 24, - //x-coordinate of the base point G - {0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, 0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00, - 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12}, - 24, - //y-coordinate of the base point G - {0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78, 0x63, 0x10, 0x11, 0xED, 0x6B, 0x24, 0xCD, 0xD5, - 0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11}, - 24, - //Base point order q - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36, - 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31}, - 24, - //Cofactor - 1, - //Fast modular reduction - secp192r1Mod -}; - -#endif -#if (SECP224K1_SUPPORT == ENABLED) - -/** - * @brief secp224k1 elliptic curve - **/ - -const EcCurveInfo secp224k1Curve = -{ - //Curve name - "secp224k1", - //Object identifier - SECP224K1_OID, - sizeof(SECP224K1_OID), - //Curve type - EC_CURVE_TYPE_SECP_K1, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xE5, 0x6D}, - 28, - //Curve parameter a - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - 28, - //Curve parameter b - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, - 28, - //x-coordinate of the base point G - {0xA1, 0x45, 0x5B, 0x33, 0x4D, 0xF0, 0x99, 0xDF, 0x30, 0xFC, 0x28, 0xA1, 0x69, 0xA4, 0x67, 0xE9, - 0xE4, 0x70, 0x75, 0xA9, 0x0F, 0x7E, 0x65, 0x0E, 0xB6, 0xB7, 0xA4, 0x5C}, - 28, - //y-coordinate of the base point G - {0x7E, 0x08, 0x9F, 0xED, 0x7F, 0xBA, 0x34, 0x42, 0x82, 0xCA, 0xFB, 0xD6, 0xF7, 0xE3, 0x19, 0xF7, - 0xC0, 0xB0, 0xBD, 0x59, 0xE2, 0xCA, 0x4B, 0xDB, 0x55, 0x6D, 0x61, 0xA5}, - 28, - //Base point order q - {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xDC, - 0xE8, 0xD2, 0xEC, 0x61, 0x84, 0xCA, 0xF0, 0xA9, 0x71, 0x76, 0x9F, 0xB1, 0xF7}, - 29, - //Cofactor - 1, - //Fast modular reduction - secp224k1Mod -}; - -#endif -#if (SECP224R1_SUPPORT == ENABLED) - -/** - * @brief secp224r1 elliptic curve - **/ - -const EcCurveInfo secp224r1Curve = -{ - //Curve name - "secp224r1", - //Object identifier - SECP224R1_OID, - sizeof(SECP224R1_OID), - //Curve type - EC_CURVE_TYPE_SECP_R1, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, - 28, - //Curve parameter a - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}, - 28, - //Curve parameter b - {0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xB0, 0xB7, - 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4}, - 28, - //x-coordinate of the base point G - {0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9, 0x4A, 0x03, 0xC1, 0xD3, - 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21}, - 28, - //y-coordinate of the base point G - {0xBD, 0x37, 0x63, 0x88, 0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6, 0xCD, 0x43, 0x75, 0xA0, - 0x5A, 0x07, 0x47, 0x64, 0x44, 0xD5, 0x81, 0x99, 0x85, 0x00, 0x7E, 0x34}, - 28, - //Base point order q - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x16, 0xA2, - 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45, 0x5C, 0x5C, 0x2A, 0x3D}, - 28, - //Cofactor - 1, - //Fast modular reduction - secp224r1Mod -}; - -#endif -#if (SECP256K1_SUPPORT == ENABLED) - -/** - * @brief secp256k1 elliptic curve - **/ - -const EcCurveInfo secp256k1Curve = -{ - //Curve name - "secp256k1", - //Object identifier - SECP256K1_OID, - sizeof(SECP256K1_OID), - //Curve type - EC_CURVE_TYPE_SECP_K1, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F}, - 32, - //Curve parameter a - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - 32, - //Curve parameter b - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07}, - 32, - //x-coordinate of the base point G - {0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, - 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98}, - 32, - //y-coordinate of the base point G - {0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65, 0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, 0xA8, - 0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19, 0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, 0xB8}, - 32, - //Base point order q - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41}, - 32, - //Cofactor - 1, - //Fast modular reduction - secp256k1Mod -}; - -#endif -#if (SECP256R1_SUPPORT == ENABLED) - -/** - * @brief secp256r1 elliptic curve - **/ - -const EcCurveInfo secp256r1Curve = -{ - //Curve name - "secp256r1", - //Object identifier - SECP256R1_OID, - sizeof(SECP256R1_OID), - //Curve type - EC_CURVE_TYPE_SECP_R1, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - 32, - //Curve parameter a - {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}, - 32, - //Curve parameter b - {0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, - 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B}, - 32, - //x-coordinate of the base point G - {0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, - 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96}, - 32, - //y-coordinate of the base point G - {0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, - 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5}, - 32, - //Base point order q - {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51}, - 32, - //Cofactor - 1, - //Fast modular reduction - secp256r1Mod -}; - -#endif -#if (SECP384R1_SUPPORT == ENABLED) - -/** - * @brief secp384r1 elliptic curve - **/ - -const EcCurveInfo secp384r1Curve = -{ - //Curve name - "secp384r1", - //Object identifier - SECP384R1_OID, - sizeof(SECP384R1_OID), - //Curve type - EC_CURVE_TYPE_SECP_R1, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}, - 48, - //Curve parameter a - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC}, - 48, - //Curve parameter b - {0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B, 0xE3, 0xF8, 0x2D, 0x19, - 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12, 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, - 0xC6, 0x56, 0x39, 0x8D, 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF}, - 48, - //x-coordinate of the base point G - {0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74, - 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98, 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, - 0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7}, - 48, - //y-coordinate of the base point G - {0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29, - 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C, 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, - 0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F}, - 48, - //Base point order q - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, - 0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73}, - 48, - //Cofactor - 1, - //Fast modular reduction - secp384r1Mod -}; - -#endif -#if (SECP521R1_SUPPORT == ENABLED) - -/** - * @brief secp521r1 elliptic curve - **/ - -const EcCurveInfo secp521r1Curve = -{ - //Curve name - "secp521r1", - //Object identifier - SECP521R1_OID, - sizeof(SECP521R1_OID), - //Curve type - EC_CURVE_TYPE_SECP_R1, - //Prime modulus p - {0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF}, - 66, - //Curve parameter a - {0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFC}, - 66, - //Curve parameter b - {0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A, 0x21, 0xA0, 0xB6, 0x85, - 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, - 0x09, 0xE1, 0x56, 0x19, 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, - 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45, 0x1F, 0xD4, 0x6B, 0x50, - 0x3F, 0x00}, - 66, - //x-coordinate of the base point G - {0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E, 0xCB, 0x66, 0x23, 0x95, - 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, - 0x3D, 0xBA, 0xA1, 0x4B, 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, - 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E, 0x7E, 0x31, 0xC2, 0xE5, - 0xBD, 0x66}, - 66, - //y-coordinate of the base point G - {0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A, 0x5F, 0xB4, 0x2C, 0x7D, - 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B, 0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, - 0x66, 0x2C, 0x97, 0xEE, 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD, - 0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE, 0x94, 0x76, 0x9F, 0xD1, - 0x66, 0x50}, - 66, - //Base point order q - {0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, - 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38, - 0x64, 0x09}, - 66, - //Cofactor - 1, - //Fast modular reduction - secp521r1Mod -}; - -#endif -#if (BRAINPOOLP160R1_SUPPORT == ENABLED) - -/** - * @brief brainpoolP160r1 elliptic curve - **/ - -const EcCurveInfo brainpoolP160r1Curve = -{ - //Curve name - "brainpoolP160r1", - //Object identifier - BRAINPOOLP160R1_OID, - sizeof(BRAINPOOLP160R1_OID), - //Curve type - EC_CURVE_TYPE_BRAINPOOLP_R1, - //Prime modulus p - {0xE9, 0x5E, 0x4A, 0x5F, 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0xC7, 0xAD, 0x95, 0xB3, 0xD8, 0x13, - 0x95, 0x15, 0x62, 0x0F}, - 20, - //Curve parameter a - {0x34, 0x0E, 0x7B, 0xE2, 0xA2, 0x80, 0xEB, 0x74, 0xE2, 0xBE, 0x61, 0xBA, 0xDA, 0x74, 0x5D, 0x97, - 0xE8, 0xF7, 0xC3, 0x00}, - 20, - //Curve parameter b - {0x1E, 0x58, 0x9A, 0x85, 0x95, 0x42, 0x34, 0x12, 0x13, 0x4F, 0xAA, 0x2D, 0xBD, 0xEC, 0x95, 0xC8, - 0xD8, 0x67, 0x5E, 0x58}, - 20, - //x-coordinate of the base point G - {0xBE, 0xD5, 0xAF, 0x16, 0xEA, 0x3F, 0x6A, 0x4F, 0x62, 0x93, 0x8C, 0x46, 0x31, 0xEB, 0x5A, 0xF7, - 0xBD, 0xBC, 0xDB, 0xC3}, - 20, - //y-coordinate of the base point G - {0x16, 0x67, 0xCB, 0x47, 0x7A, 0x1A, 0x8E, 0xC3, 0x38, 0xF9, 0x47, 0x41, 0x66, 0x9C, 0x97, 0x63, - 0x16, 0xDA, 0x63, 0x21}, - 20, - //Base point order q - {0xE9, 0x5E, 0x4A, 0x5F, 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0x59, 0x91, 0xD4, 0x50, 0x29, 0x40, - 0x9E, 0x60, 0xFC, 0x09}, - 20, - //Cofactor - 1, - //Fast modular reduction - NULL -}; - -#endif -#if (BRAINPOOLP192R1_SUPPORT == ENABLED) - -/** - * @brief brainpoolP192r1 elliptic curve - **/ - -const EcCurveInfo brainpoolP192r1Curve = -{ - //Curve name - "brainpoolP192r1", - //Object identifier - BRAINPOOLP192R1_OID, - sizeof(BRAINPOOLP192R1_OID), - //Curve type - EC_CURVE_TYPE_BRAINPOOLP_R1, - //Prime modulus p - {0xC3, 0x02, 0xF4, 0x1D, 0x93, 0x2A, 0x36, 0xCD, 0xA7, 0xA3, 0x46, 0x30, 0x93, 0xD1, 0x8D, 0xB7, - 0x8F, 0xCE, 0x47, 0x6D, 0xE1, 0xA8, 0x62, 0x97}, - 24, - //Curve parameter a - {0x6A, 0x91, 0x17, 0x40, 0x76, 0xB1, 0xE0, 0xE1, 0x9C, 0x39, 0xC0, 0x31, 0xFE, 0x86, 0x85, 0xC1, - 0xCA, 0xE0, 0x40, 0xE5, 0xC6, 0x9A, 0x28, 0xEF}, - 24, - //Curve parameter b - {0x46, 0x9A, 0x28, 0xEF, 0x7C, 0x28, 0xCC, 0xA3, 0xDC, 0x72, 0x1D, 0x04, 0x4F, 0x44, 0x96, 0xBC, - 0xCA, 0x7E, 0xF4, 0x14, 0x6F, 0xBF, 0x25, 0xC9}, - 24, - //x-coordinate of the base point G - {0xC0, 0xA0, 0x64, 0x7E, 0xAA, 0xB6, 0xA4, 0x87, 0x53, 0xB0, 0x33, 0xC5, 0x6C, 0xB0, 0xF0, 0x90, - 0x0A, 0x2F, 0x5C, 0x48, 0x53, 0x37, 0x5F, 0xD6}, - 24, - //y-coordinate of the base point G - {0x14, 0xB6, 0x90, 0x86, 0x6A, 0xBD, 0x5B, 0xB8, 0x8B, 0x5F, 0x48, 0x28, 0xC1, 0x49, 0x00, 0x02, - 0xE6, 0x77, 0x3F, 0xA2, 0xFA, 0x29, 0x9B, 0x8F}, - 24, - //Base point order q - {0xC3, 0x02, 0xF4, 0x1D, 0x93, 0x2A, 0x36, 0xCD, 0xA7, 0xA3, 0x46, 0x2F, 0x9E, 0x9E, 0x91, 0x6B, - 0x5B, 0xE8, 0xF1, 0x02, 0x9A, 0xC4, 0xAC, 0xC1}, - 24, - //Cofactor - 1, - //Fast modular reduction - NULL -}; - -#endif -#if (BRAINPOOLP224R1_SUPPORT == ENABLED) - -/** - * @brief brainpoolP224r1 elliptic curve - **/ - -const EcCurveInfo brainpoolP224r1Curve = -{ - //Curve name - "brainpoolP224r1", - //Object identifier - BRAINPOOLP224R1_OID, - sizeof(BRAINPOOLP224R1_OID), - //Curve type - EC_CURVE_TYPE_BRAINPOOLP_R1, - //Prime modulus p - {0xD7, 0xC1, 0x34, 0xAA, 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25, 0x75, 0xD1, 0xD7, 0x87, - 0xB0, 0x9F, 0x07, 0x57, 0x97, 0xDA, 0x89, 0xF5, 0x7E, 0xC8, 0xC0, 0xFF}, - 28, - //Curve parameter a - {0x68, 0xA5, 0xE6, 0x2C, 0xA9, 0xCE, 0x6C, 0x1C, 0x29, 0x98, 0x03, 0xA6, 0xC1, 0x53, 0x0B, 0x51, - 0x4E, 0x18, 0x2A, 0xD8, 0xB0, 0x04, 0x2A, 0x59, 0xCA, 0xD2, 0x9F, 0x43}, - 28, - //Curve parameter b - {0x25, 0x80, 0xF6, 0x3C, 0xCF, 0xE4, 0x41, 0x38, 0x87, 0x07, 0x13, 0xB1, 0xA9, 0x23, 0x69, 0xE3, - 0x3E, 0x21, 0x35, 0xD2, 0x66, 0xDB, 0xB3, 0x72, 0x38, 0x6C, 0x40, 0x0B}, - 28, - //x-coordinate of the base point G - {0x0D, 0x90, 0x29, 0xAD, 0x2C, 0x7E, 0x5C, 0xF4, 0x34, 0x08, 0x23, 0xB2, 0xA8, 0x7D, 0xC6, 0x8C, - 0x9E, 0x4C, 0xE3, 0x17, 0x4C, 0x1E, 0x6E, 0xFD, 0xEE, 0x12, 0xC0, 0x7D}, - 28, - //y-coordinate of the base point G - {0x58, 0xAA, 0x56, 0xF7, 0x72, 0xC0, 0x72, 0x6F, 0x24, 0xC6, 0xB8, 0x9E, 0x4E, 0xCD, 0xAC, 0x24, - 0x35, 0x4B, 0x9E, 0x99, 0xCA, 0xA3, 0xF6, 0xD3, 0x76, 0x14, 0x02, 0xCD}, - 28, - //Base point order q - {0xD7, 0xC1, 0x34, 0xAA, 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25, 0x75, 0xD0, 0xFB, 0x98, - 0xD1, 0x16, 0xBC, 0x4B, 0x6D, 0xDE, 0xBC, 0xA3, 0xA5, 0xA7, 0x93, 0x9F}, - 28, - //Cofactor - 1, - //Fast modular reduction - NULL -}; - -#endif -#if (BRAINPOOLP256R1_SUPPORT == ENABLED) - -/** - * @brief brainpoolP256r1 elliptic curve - **/ - -const EcCurveInfo brainpoolP256r1Curve = -{ - //Curve name - "brainpoolP256r1", - //Object identifier - BRAINPOOLP256R1_OID, - sizeof(BRAINPOOLP256R1_OID), - //Curve type - EC_CURVE_TYPE_BRAINPOOLP_R1, - //Prime modulus p - {0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72, - 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28, 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77}, - 32, - //Curve parameter a - {0x7D, 0x5A, 0x09, 0x75, 0xFC, 0x2C, 0x30, 0x57, 0xEE, 0xF6, 0x75, 0x30, 0x41, 0x7A, 0xFF, 0xE7, - 0xFB, 0x80, 0x55, 0xC1, 0x26, 0xDC, 0x5C, 0x6C, 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9}, - 32, - //Curve parameter b - {0x26, 0xDC, 0x5C, 0x6C, 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9, 0xBB, 0xD7, 0x7C, 0xBF, - 0x95, 0x84, 0x16, 0x29, 0x5C, 0xF7, 0xE1, 0xCE, 0x6B, 0xCC, 0xDC, 0x18, 0xFF, 0x8C, 0x07, 0xB6}, - 32, - //x-coordinate of the base point G - {0x8B, 0xD2, 0xAE, 0xB9, 0xCB, 0x7E, 0x57, 0xCB, 0x2C, 0x4B, 0x48, 0x2F, 0xFC, 0x81, 0xB7, 0xAF, - 0xB9, 0xDE, 0x27, 0xE1, 0xE3, 0xBD, 0x23, 0xC2, 0x3A, 0x44, 0x53, 0xBD, 0x9A, 0xCE, 0x32, 0x62}, - 32, - //y-coordinate of the base point G - {0x54, 0x7E, 0xF8, 0x35, 0xC3, 0xDA, 0xC4, 0xFD, 0x97, 0xF8, 0x46, 0x1A, 0x14, 0x61, 0x1D, 0xC9, - 0xC2, 0x77, 0x45, 0x13, 0x2D, 0xED, 0x8E, 0x54, 0x5C, 0x1D, 0x54, 0xC7, 0x2F, 0x04, 0x69, 0x97}, - 32, - //Base point order q - {0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71, - 0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7, 0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7}, - 32, - //Cofactor - 1, - //Fast modular reduction - NULL -}; - -#endif -#if (BRAINPOOLP320R1_SUPPORT == ENABLED) - -/** - * @brief brainpoolP320r1 elliptic curve - **/ - -const EcCurveInfo brainpoolP320r1Curve = -{ - //Curve name - "brainpoolP320r1", - //Object identifier - BRAINPOOLP320R1_OID, - sizeof(BRAINPOOLP320R1_OID), - //Curve type - EC_CURVE_TYPE_BRAINPOOLP_R1, - //Prime modulus p - {0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E, 0xD2, 0x01, 0xE0, 0x65, - 0xF9, 0x8F, 0xCF, 0xA6, 0xF6, 0xF4, 0x0D, 0xEF, 0x4F, 0x92, 0xB9, 0xEC, 0x78, 0x93, 0xEC, 0x28, - 0xFC, 0xD4, 0x12, 0xB1, 0xF1, 0xB3, 0x2E, 0x27}, - 40, - //Curve parameter a - {0x3E, 0xE3, 0x0B, 0x56, 0x8F, 0xBA, 0xB0, 0xF8, 0x83, 0xCC, 0xEB, 0xD4, 0x6D, 0x3F, 0x3B, 0xB8, - 0xA2, 0xA7, 0x35, 0x13, 0xF5, 0xEB, 0x79, 0xDA, 0x66, 0x19, 0x0E, 0xB0, 0x85, 0xFF, 0xA9, 0xF4, - 0x92, 0xF3, 0x75, 0xA9, 0x7D, 0x86, 0x0E, 0xB4}, - 40, - //Curve parameter b - {0x52, 0x08, 0x83, 0x94, 0x9D, 0xFD, 0xBC, 0x42, 0xD3, 0xAD, 0x19, 0x86, 0x40, 0x68, 0x8A, 0x6F, - 0xE1, 0x3F, 0x41, 0x34, 0x95, 0x54, 0xB4, 0x9A, 0xCC, 0x31, 0xDC, 0xCD, 0x88, 0x45, 0x39, 0x81, - 0x6F, 0x5E, 0xB4, 0xAC, 0x8F, 0xB1, 0xF1, 0xA6}, - 40, - //x-coordinate of the base point G - {0x43, 0xBD, 0x7E, 0x9A, 0xFB, 0x53, 0xD8, 0xB8, 0x52, 0x89, 0xBC, 0xC4, 0x8E, 0xE5, 0xBF, 0xE6, - 0xF2, 0x01, 0x37, 0xD1, 0x0A, 0x08, 0x7E, 0xB6, 0xE7, 0x87, 0x1E, 0x2A, 0x10, 0xA5, 0x99, 0xC7, - 0x10, 0xAF, 0x8D, 0x0D, 0x39, 0xE2, 0x06, 0x11}, - 40, - //y-coordinate of the base point G - {0x14, 0xFD, 0xD0, 0x55, 0x45, 0xEC, 0x1C, 0xC8, 0xAB, 0x40, 0x93, 0x24, 0x7F, 0x77, 0x27, 0x5E, - 0x07, 0x43, 0xFF, 0xED, 0x11, 0x71, 0x82, 0xEA, 0xA9, 0xC7, 0x78, 0x77, 0xAA, 0xAC, 0x6A, 0xC7, - 0xD3, 0x52, 0x45, 0xD1, 0x69, 0x2E, 0x8E, 0xE1}, - 40, - //Base point order q - {0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E, 0xD2, 0x01, 0xE0, 0x65, - 0xF9, 0x8F, 0xCF, 0xA5, 0xB6, 0x8F, 0x12, 0xA3, 0x2D, 0x48, 0x2E, 0xC7, 0xEE, 0x86, 0x58, 0xE9, - 0x86, 0x91, 0x55, 0x5B, 0x44, 0xC5, 0x93, 0x11}, - 40, - //Cofactor - 1, - //Fast modular reduction - NULL -}; - -#endif -#if (BRAINPOOLP384R1_SUPPORT == ENABLED) - -/** - * @brief brainpoolP384r1 elliptic curve - **/ - -const EcCurveInfo brainpoolP384r1Curve = -{ - //Curve name - "brainpoolP384r1", - //Object identifier - BRAINPOOLP384R1_OID, - sizeof(BRAINPOOLP384R1_OID), - //Curve type - EC_CURVE_TYPE_BRAINPOOLP_R1, - //Prime modulus p - {0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E, 0x50, 0xE6, 0x41, 0xDF, - 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB4, 0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11, 0x23, - 0xAC, 0xD3, 0xA7, 0x29, 0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xEC, 0x53}, - 48, - //Curve parameter a - {0x7B, 0xC3, 0x82, 0xC6, 0x3D, 0x8C, 0x15, 0x0C, 0x3C, 0x72, 0x08, 0x0A, 0xCE, 0x05, 0xAF, 0xA0, - 0xC2, 0xBE, 0xA2, 0x8E, 0x4F, 0xB2, 0x27, 0x87, 0x13, 0x91, 0x65, 0xEF, 0xBA, 0x91, 0xF9, 0x0F, - 0x8A, 0xA5, 0x81, 0x4A, 0x50, 0x3A, 0xD4, 0xEB, 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26}, - 48, - //Curve parameter b - {0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26, 0x8B, 0x39, 0xB5, 0x54, 0x16, 0xF0, 0x44, 0x7C, - 0x2F, 0xB7, 0x7D, 0xE1, 0x07, 0xDC, 0xD2, 0xA6, 0x2E, 0x88, 0x0E, 0xA5, 0x3E, 0xEB, 0x62, 0xD5, - 0x7C, 0xB4, 0x39, 0x02, 0x95, 0xDB, 0xC9, 0x94, 0x3A, 0xB7, 0x86, 0x96, 0xFA, 0x50, 0x4C, 0x11}, - 48, - //x-coordinate of the base point G - {0x1D, 0x1C, 0x64, 0xF0, 0x68, 0xCF, 0x45, 0xFF, 0xA2, 0xA6, 0x3A, 0x81, 0xB7, 0xC1, 0x3F, 0x6B, - 0x88, 0x47, 0xA3, 0xE7, 0x7E, 0xF1, 0x4F, 0xE3, 0xDB, 0x7F, 0xCA, 0xFE, 0x0C, 0xBD, 0x10, 0xE8, - 0xE8, 0x26, 0xE0, 0x34, 0x36, 0xD6, 0x46, 0xAA, 0xEF, 0x87, 0xB2, 0xE2, 0x47, 0xD4, 0xAF, 0x1E}, - 48, - //y-coordinate of the base point G - {0x8A, 0xBE, 0x1D, 0x75, 0x20, 0xF9, 0xC2, 0xA4, 0x5C, 0xB1, 0xEB, 0x8E, 0x95, 0xCF, 0xD5, 0x52, - 0x62, 0xB7, 0x0B, 0x29, 0xFE, 0xEC, 0x58, 0x64, 0xE1, 0x9C, 0x05, 0x4F, 0xF9, 0x91, 0x29, 0x28, - 0x0E, 0x46, 0x46, 0x21, 0x77, 0x91, 0x81, 0x11, 0x42, 0x82, 0x03, 0x41, 0x26, 0x3C, 0x53, 0x15}, - 48, - //Base point order q - {0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E, 0x50, 0xE6, 0x41, 0xDF, - 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB3, 0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25, 0xA7, - 0xCF, 0x3A, 0xB6, 0xAF, 0x6B, 0x7F, 0xC3, 0x10, 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04, 0x65, 0x65}, - 48, - //Cofactor - 1, - //Fast modular reduction - NULL -}; - -#endif -#if (BRAINPOOLP512R1_SUPPORT == ENABLED) - -/** - * @brief brainpoolP512r1 elliptic curve - **/ - -const EcCurveInfo brainpoolP512r1Curve = -{ - //Curve name - "brainpoolP512r1", - //Object identifier - BRAINPOOLP512R1_OID, - sizeof(BRAINPOOLP512R1_OID), - //Curve type - EC_CURVE_TYPE_BRAINPOOLP_R1, - //Prime modulus p - {0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE, 0x33, 0xC9, 0xFC, 0x07, - 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E, 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x71, - 0x7D, 0x4D, 0x9B, 0x00, 0x9B, 0xC6, 0x68, 0x42, 0xAE, 0xCD, 0xA1, 0x2A, 0xE6, 0xA3, 0x80, 0xE6, - 0x28, 0x81, 0xFF, 0x2F, 0x2D, 0x82, 0xC6, 0x85, 0x28, 0xAA, 0x60, 0x56, 0x58, 0x3A, 0x48, 0xF3}, - 64, - //Curve parameter a - {0x78, 0x30, 0xA3, 0x31, 0x8B, 0x60, 0x3B, 0x89, 0xE2, 0x32, 0x71, 0x45, 0xAC, 0x23, 0x4C, 0xC5, - 0x94, 0xCB, 0xDD, 0x8D, 0x3D, 0xF9, 0x16, 0x10, 0xA8, 0x34, 0x41, 0xCA, 0xEA, 0x98, 0x63, 0xBC, - 0x2D, 0xED, 0x5D, 0x5A, 0xA8, 0x25, 0x3A, 0xA1, 0x0A, 0x2E, 0xF1, 0xC9, 0x8B, 0x9A, 0xC8, 0xB5, - 0x7F, 0x11, 0x17, 0xA7, 0x2B, 0xF2, 0xC7, 0xB9, 0xE7, 0xC1, 0xAC, 0x4D, 0x77, 0xFC, 0x94, 0xCA}, - 64, - //Curve parameter b - {0x3D, 0xF9, 0x16, 0x10, 0xA8, 0x34, 0x41, 0xCA, 0xEA, 0x98, 0x63, 0xBC, 0x2D, 0xED, 0x5D, 0x5A, - 0xA8, 0x25, 0x3A, 0xA1, 0x0A, 0x2E, 0xF1, 0xC9, 0x8B, 0x9A, 0xC8, 0xB5, 0x7F, 0x11, 0x17, 0xA7, - 0x2B, 0xF2, 0xC7, 0xB9, 0xE7, 0xC1, 0xAC, 0x4D, 0x77, 0xFC, 0x94, 0xCA, 0xDC, 0x08, 0x3E, 0x67, - 0x98, 0x40, 0x50, 0xB7, 0x5E, 0xBA, 0xE5, 0xDD, 0x28, 0x09, 0xBD, 0x63, 0x80, 0x16, 0xF7, 0x23}, - 64, - //x-coordinate of the base point G - {0x81, 0xAE, 0xE4, 0xBD, 0xD8, 0x2E, 0xD9, 0x64, 0x5A, 0x21, 0x32, 0x2E, 0x9C, 0x4C, 0x6A, 0x93, - 0x85, 0xED, 0x9F, 0x70, 0xB5, 0xD9, 0x16, 0xC1, 0xB4, 0x3B, 0x62, 0xEE, 0xF4, 0xD0, 0x09, 0x8E, - 0xFF, 0x3B, 0x1F, 0x78, 0xE2, 0xD0, 0xD4, 0x8D, 0x50, 0xD1, 0x68, 0x7B, 0x93, 0xB9, 0x7D, 0x5F, - 0x7C, 0x6D, 0x50, 0x47, 0x40, 0x6A, 0x5E, 0x68, 0x8B, 0x35, 0x22, 0x09, 0xBC, 0xB9, 0xF8, 0x22}, - 64, - //y-coordinate of the base point G - {0x7D, 0xDE, 0x38, 0x5D, 0x56, 0x63, 0x32, 0xEC, 0xC0, 0xEA, 0xBF, 0xA9, 0xCF, 0x78, 0x22, 0xFD, - 0xF2, 0x09, 0xF7, 0x00, 0x24, 0xA5, 0x7B, 0x1A, 0xA0, 0x00, 0xC5, 0x5B, 0x88, 0x1F, 0x81, 0x11, - 0xB2, 0xDC, 0xDE, 0x49, 0x4A, 0x5F, 0x48, 0x5E, 0x5B, 0xCA, 0x4B, 0xD8, 0x8A, 0x27, 0x63, 0xAE, - 0xD1, 0xCA, 0x2B, 0x2F, 0xA8, 0xF0, 0x54, 0x06, 0x78, 0xCD, 0x1E, 0x0F, 0x3A, 0xD8, 0x08, 0x92}, - 64, - //Base point order q - {0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE, 0x33, 0xC9, 0xFC, 0x07, - 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E, 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x70, - 0x55, 0x3E, 0x5C, 0x41, 0x4C, 0xA9, 0x26, 0x19, 0x41, 0x86, 0x61, 0x19, 0x7F, 0xAC, 0x10, 0x47, - 0x1D, 0xB1, 0xD3, 0x81, 0x08, 0x5D, 0xDA, 0xDD, 0xB5, 0x87, 0x96, 0x82, 0x9C, 0xA9, 0x00, 0x69}, - 64, - //Cofactor - 1, - //Fast modular reduction - NULL -}; - -#endif -#if (SM2_SUPPORT == ENABLED) - -/** - * @brief SM2 elliptic curve - **/ - -const EcCurveInfo sm2Curve = -{ - //Curve name - "curveSM2", - //Object identifier - SM2_OID, - sizeof(SM2_OID), - //Curve type - EC_CURVE_TYPE_SECP_R1, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - 32, - //Curve parameter a - {0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}, - 32, - //Curve parameter b - {0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34, 0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7, - 0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92, 0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93}, - 32, - //x-coordinate of the base point G - {0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19, 0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94, - 0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1, 0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7}, - 32, - //y-coordinate of the base point G - {0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C, 0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53, - 0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40, 0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0}, - 32, - //Base point order q - {0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x72, 0x03, 0xDF, 0x6B, 0x21, 0xC6, 0x05, 0x2B, 0x53, 0xBB, 0xF4, 0x09, 0x39, 0xD5, 0x41, 0x23}, - 32, - //Cofactor - 1, - //Fast modular reduction - sm2Mod -}; - -#endif -#if (X25519_SUPPORT == ENABLED) - -/** - * @brief Curve25519 elliptic curve - **/ - -const EcCurveInfo x25519Curve = -{ - //Curve name - "curve25519", - //Object identifier - X25519_OID, - sizeof(X25519_OID), - //Curve type - EC_CURVE_TYPE_X25519, - //Prime modulus p - {0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED}, - 32, - //Curve parameter a - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x6D, 0x06}, - 32, - //Curve parameter b - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - 32, - //u-coordinate of the base point G - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09}, - 32, - //v-coordinate of the base point G - {0x20, 0xAE, 0x19, 0xA1, 0xB8, 0xA0, 0x86, 0xB4, 0xE0, 0x1E, 0xDD, 0x2C, 0x77, 0x48, 0xD1, 0x4C, - 0x92, 0x3D, 0x4D, 0x7E, 0x6D, 0x7C, 0x61, 0xB2, 0x29, 0xE9, 0xC5, 0xA2, 0x7E, 0xCE, 0xD3, 0xD9}, - 32, - //Base point order q - {0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6, 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED}, - 32, - //Cofactor - 8, - //Fast modular reduction - NULL -}; - -#endif -#if (X448_SUPPORT == ENABLED) - -/** - * @brief Curve448 elliptic curve - **/ - -const EcCurveInfo x448Curve = -{ - //Curve name - "curve448", - //Object identifier - X448_OID, - sizeof(X448_OID), - //Curve type - EC_CURVE_TYPE_X448, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - 56, - //Curve parameter a - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x62, 0xA6}, - 56, - //Curve parameter b - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - 56, - //u-coordinate of the base point G - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, - 56, - //v-coordinate of the base point G - {0x7D, 0x23, 0x5D, 0x12, 0x95, 0xF5, 0xB1, 0xF6, 0x6C, 0x98, 0xAB, 0x6E, 0x58, 0x32, 0x6F, 0xCE, - 0xCB, 0xAE, 0x5D, 0x34, 0xF5, 0x55, 0x45, 0xD0, 0x60, 0xF7, 0x5D, 0xC2, 0x8D, 0xF3, 0xF6, 0xED, - 0xB8, 0x02, 0x7E, 0x23, 0x46, 0x43, 0x0D, 0x21, 0x13, 0x12, 0xC4, 0xB1, 0x50, 0x67, 0x7A, 0xF7, - 0x6F, 0xD7, 0x22, 0x3D, 0x45, 0x7B, 0x5B, 0x1A}, - 56, - //Base point order q - {0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0xCA, 0x23, 0xE9, - 0xC4, 0x4E, 0xDB, 0x49, 0xAE, 0xD6, 0x36, 0x90, 0x21, 0x6C, 0xC2, 0x72, 0x8D, 0xC5, 0x8F, 0x55, - 0x23, 0x78, 0xC2, 0x92, 0xAB, 0x58, 0x44, 0xF3}, - 56, - //Cofactor - 4, - //Fast modular reduction - NULL -}; - -#endif -#if (ED25519_SUPPORT == ENABLED) - -/** - * @brief Ed25519 elliptic curve - **/ - -const EcCurveInfo ed25519Curve = -{ - //Curve name - "Ed25519", - //Object identifier - ED25519_OID, - sizeof(ED25519_OID), - //Curve type - EC_CURVE_TYPE_ED25519, - //Prime modulus p - {0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED}, - 32, - //Curve parameter a - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x6D, 0x06}, - 32, - //Curve parameter b - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - 32, - //x-coordinate of the base point G - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09}, - 32, - //y-coordinate of the base point G - {0x20, 0xAE, 0x19, 0xA1, 0xB8, 0xA0, 0x86, 0xB4, 0xE0, 0x1E, 0xDD, 0x2C, 0x77, 0x48, 0xD1, 0x4C, - 0x92, 0x3D, 0x4D, 0x7E, 0x6D, 0x7C, 0x61, 0xB2, 0x29, 0xE9, 0xC5, 0xA2, 0x7E, 0xCE, 0xD3, 0xD9}, - 32, - //Base point order q - {0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6, 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED}, - 32, - //Cofactor - 8, - //Fast modular reduction - NULL -}; - -#endif -#if (ED448_SUPPORT == ENABLED) - -/** - * @brief Ed448 elliptic curve - **/ - -const EcCurveInfo ed448Curve = -{ - //Curve name - "Ed448", - //Object identifier - ED448_OID, - sizeof(ED448_OID), - //Curve type - EC_CURVE_TYPE_ED448, - //Prime modulus p - {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, - 56, - //Curve parameter a - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x62, 0xA6}, - 56, - //Curve parameter b - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - 56, - //x-coordinate of the base point G - {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, - 56, - //y-coordinate of the base point G - {0x7D, 0x23, 0x5D, 0x12, 0x95, 0xF5, 0xB1, 0xF6, 0x6C, 0x98, 0xAB, 0x6E, 0x58, 0x32, 0x6F, 0xCE, - 0xCB, 0xAE, 0x5D, 0x34, 0xF5, 0x55, 0x45, 0xD0, 0x60, 0xF7, 0x5D, 0xC2, 0x8D, 0xF3, 0xF6, 0xED, - 0xB8, 0x02, 0x7E, 0x23, 0x46, 0x43, 0x0D, 0x21, 0x13, 0x12, 0xC4, 0xB1, 0x50, 0x67, 0x7A, 0xF7, - 0x6F, 0xD7, 0x22, 0x3D, 0x45, 0x7B, 0x5B, 0x1A}, - 56, - //Base point order q - {0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0xCA, 0x23, 0xE9, - 0xC4, 0x4E, 0xDB, 0x49, 0xAE, 0xD6, 0x36, 0x90, 0x21, 0x6C, 0xC2, 0x72, 0x8D, 0xC5, 0x8F, 0x55, - 0x23, 0x78, 0xC2, 0x92, 0xAB, 0x58, 0x44, 0xF3}, - 56, - //Cofactor - 4, - //Fast modular reduction - NULL -}; - -#endif -#if (SECP128R1_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (secp128r1 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t secp128r1Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi t; - - //Initialize multiple precision integers - mpiInit(&t); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 32 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 32 / MPI_INT_SIZE)); - - //Perform modular reduction - do - { - //Compute T = 0 | 0 | 0 | 0 | A7 | A6 | A5 | A4 - COPY_WORD32(&t, 0, a, 4, 4); - CLEAR_WORD32(&t, 4, 4); - - //Clear A7 | A6 | A5 | A4 - CLEAR_WORD32(a, 4, 4); - - //Compute A = A + T + (T << 97) - MPI_CHECK(mpiAdd(a, a, &t)); - MPI_CHECK(mpiShiftLeft(&t, 97)); - MPI_CHECK(mpiAdd(a, a, &t)); - - //Check for end condition - } while(mpiComp(a, p) > 0); - -end: - //Release multiple precision integers - mpiFree(&t); - - //Return status code - return error; -} - -#endif -#if (SECP128R2_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (secp128r2 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t secp128r2Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi t; - - //Initialize multiple precision integers - mpiInit(&t); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 32 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 32 / MPI_INT_SIZE)); - - //Perform modular reduction - do - { - //Compute T = 0 | 0 | 0 | 0 | A7 | A6 | A5 | A4 - COPY_WORD32(&t, 0, a, 4, 4); - CLEAR_WORD32(&t, 4, 4); - - //Clear A7 | A6 | A5 | A4 - CLEAR_WORD32(a, 4, 4); - - //Compute A = A + T + (T << 97) - MPI_CHECK(mpiAdd(a, a, &t)); - MPI_CHECK(mpiShiftLeft(&t, 97)); - MPI_CHECK(mpiAdd(a, a, &t)); - - //Check for end condition - } while(mpiComp(a, p) > 0); - -end: - //Release multiple precision integers - mpiFree(&t); - - //Return status code - return error; -} - -#endif -#if (SECP160K1_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (secp160k1 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t secp160k1Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi t; - - //Initialize multiple precision integers - mpiInit(&t); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 40 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 24 / MPI_INT_SIZE)); - - //Perform modular reduction - do - { - //Compute T = A9 | A8 | A7 | A6 | A5 | 0 - CLEAR_WORD32(&t, 0, 1); - COPY_WORD32(&t, 1, a, 5, 5); - - //Clear A9 | A8 | A7 | A6 | A5 - CLEAR_WORD32(a, 5, 5); - - //Compute A = A + T - MPI_CHECK(mpiAdd(a, a, &t)); - //Compute T = T >> 32 - MPI_CHECK(mpiShiftRight(&t, 32)); - //Compute A = A + (21389 * T) - MPI_CHECK(mpiMulInt(&t, &t, 21389)); - MPI_CHECK(mpiAdd(a, a, &t)); - - //Check for end condition - } while(mpiComp(a, p) > 0); - -end: - //Release multiple precision integers - mpiFree(&t); - - //Return status code - return error; -} - -#endif -#if (SECP160R1_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (secp160r1 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t secp160r1Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi t; - - //Initialize multiple precision integers - mpiInit(&t); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 40 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 24 / MPI_INT_SIZE)); - - //Perform modular reduction - do - { - //Compute T = 0 | A9 | A8 | A7 | A6 | A5 - COPY_WORD32(&t, 0, a, 5, 5); - CLEAR_WORD32(&t, 5, 1); - - //Clear A9 | A8 | A7 | A6 | A5 - CLEAR_WORD32(a, 5, 5); - - //Compute A = A + T + (T << 31) - MPI_CHECK(mpiAdd(a, a, &t)); - MPI_CHECK(mpiShiftLeft(&t, 31)); - MPI_CHECK(mpiAdd(a, a, &t)); - - //Check for end condition - } while(mpiComp(a, p) > 0); - -end: - //Release multiple precision integers - mpiFree(&t); - - //Return status code - return error; -} - -#endif -#if (SECP160R2_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (secp160r2 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t secp160r2Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi t; - - //Initialize multiple precision integers - mpiInit(&t); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 40 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 24 / MPI_INT_SIZE)); - - //Perform modular reduction - do - { - //Compute T = A9 | A8 | A7 | A6 | A5 | 0 - CLEAR_WORD32(&t, 0, 1); - COPY_WORD32(&t, 1, a, 5, 5); - - //Clear A9 | A8 | A7 | A6 | A5 - CLEAR_WORD32(a, 5, 5); - - //Compute A = A + T - MPI_CHECK(mpiAdd(a, a, &t)); - //Compute T = T >> 32 - MPI_CHECK(mpiShiftRight(&t, 32)); - //Compute A = A + (21389 * T) - MPI_CHECK(mpiMulInt(&t, &t, 21389)); - MPI_CHECK(mpiAdd(a, a, &t)); - - //Check for end condition - } while(mpiComp(a, p) > 0); - -end: - //Release multiple precision integers - mpiFree(&t); - - //Return status code - return error; -} - -#endif -#if (SECP192K1_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (secp192k1 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t secp192k1Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi t; - - //Initialize multiple precision integers - mpiInit(&t); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 48 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 28 / MPI_INT_SIZE)); - - //Perform modular reduction - do - { - //Compute T = A11 | A10 | A9 | A8 | A7 | A6 | 0 - CLEAR_WORD32(&t, 0, 1); - COPY_WORD32(&t, 1, a, 6, 6); - - //Clear A11 | A10 | A9 | A8 | A7 | A6 - CLEAR_WORD32(a, 6, 6); - - //Compute A = A + T - MPI_CHECK(mpiAdd(a, a, &t)); - //Compute T = T >> 32 - MPI_CHECK(mpiShiftRight(&t, 32)); - //Compute A = A + (4553 * T) - MPI_CHECK(mpiMulInt(&t, &t, 4553)); - MPI_CHECK(mpiAdd(a, a, &t)); - - //Check for end condition - } while(mpiComp(a, p) > 0); - -end: - //Release multiple precision integers - mpiFree(&t); - - //Return status code - return error; -} - -#endif -#if (SECP192R1_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (secp192r1 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t secp192r1Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi s; - Mpi t; - - //Initialize multiple precision integers - mpiInit(&s); - mpiInit(&t); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 48 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&s, 24 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 24 / MPI_INT_SIZE)); - - //Compute T = A5 | A4 | A3 | A2 | A1 | A0 - COPY_WORD32(&t, 0, a, 0, 6); - - //Compute S1 = 0 | 0 | A7 | A6 | A7 | A6 - COPY_WORD32(&s, 0, a, 6, 2); - COPY_WORD32(&s, 2, a, 6, 2); - CLEAR_WORD32(&s, 4, 2); - //Compute T = T + S1 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S2 = A9 | A8 | A9 | A8 | 0 | 0 - CLEAR_WORD32(&s, 0, 2); - COPY_WORD32(&s, 2, a, 8, 2); - COPY_WORD32(&s, 4, a, 8, 2); - //Compute T = T + S2 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S3 = A11 | A10 | A11 | A10 | A11 | A10 - COPY_WORD32(&s, 0, a, 10, 2); - COPY_WORD32(&s, 2, a, 10, 2); - COPY_WORD32(&s, 4, a, 10, 2); - //Compute T = T + S3 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute (T + S1 + S2 + S3) mod p - while(mpiComp(&t, p) >= 0) - { - MPI_CHECK(mpiSub(&t, &t, p)); - } - - //Save result - MPI_CHECK(mpiCopy(a, &t)); - -end: - //Release multiple precision integers - mpiFree(&s); - mpiFree(&t); - - //Return status code - return error; -} - -#endif -#if (SECP224K1_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (secp224k1 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t secp224k1Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi t; - - //Initialize multiple precision integers - mpiInit(&t); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 56 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 32 / MPI_INT_SIZE)); - - //Perform modular reduction - do - { - //Compute T = A13 | A12 | A11 | A10 | A9 | A8 | A7 | 0 - CLEAR_WORD32(&t, 0, 1); - COPY_WORD32(&t, 1, a, 7, 7); - - //Clear A13 | A12 | A11 | A10 | A9 | A8 | A7 - CLEAR_WORD32(a, 7, 7); - - //Compute A = A + T - MPI_CHECK(mpiAdd(a, a, &t)); - //Compute T = T >> 32 - MPI_CHECK(mpiShiftRight(&t, 32)); - //Compute A = A + (6803 * T) - MPI_CHECK(mpiMulInt(&t, &t, 6803)); - MPI_CHECK(mpiAdd(a, a, &t)); - - //Check for end condition - } while(mpiComp(a, p) > 0); - -end: - //Release multiple precision integers - mpiFree(&t); - - //Return status code - return error; -} - -#endif -#if (SECP224R1_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (secp224r1 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t secp224r1Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi s; - Mpi t; - - //Initialize multiple precision integers - mpiInit(&s); - mpiInit(&t); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 56 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&s, 28 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 28 / MPI_INT_SIZE)); - - //Compute T = A6 | A5 | A4 | A3 | A2 | A1 | A0 - COPY_WORD32(&t, 0, a, 0, 7); - - //Compute S1 = A10 | A9 | A8 | A7 | 0 | 0 | 0 - CLEAR_WORD32(&s, 0, 3); - COPY_WORD32(&s, 3, a, 7, 4); - //Compute T = T + S1 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S2 = 0 | A13 | A12 | A11 | 0 | 0 | 0 - CLEAR_WORD32(&s, 0, 3); - COPY_WORD32(&s, 3, a, 11, 3); - CLEAR_WORD32(&s, 6, 1); - //Compute T = T + S2 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute D1 = A13 | A12 | A11 | A10 | A9 | A8 | A7 - COPY_WORD32(&s, 0, a, 7, 7); - //Compute T = T - D1 - MPI_CHECK(mpiSub(&t, &t, &s)); - - //Compute D2 = 0 | 0 | 0 | 0 | A13 | A12 | A11 - COPY_WORD32(&s, 0, a, 11, 3); - CLEAR_WORD32(&s, 3, 4); - //Compute T = T - D2 - MPI_CHECK(mpiSub(&t, &t, &s)); - - //Compute (T + S1 + S2 - D1 - D2) mod p - while(mpiComp(&t, p) >= 0) - { - MPI_CHECK(mpiSub(&t, &t, p)); - } - - while(mpiCompInt(&t, 0) < 0) - { - MPI_CHECK(mpiAdd(&t, &t, p)); - } - - //Save result - MPI_CHECK(mpiCopy(a, &t)); - -end: - //Release multiple precision integers - mpiFree(&s); - mpiFree(&t); - - //Return status code - return error; -} - -#endif -#if (SECP256K1_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (secp256k1 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t secp256k1Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi t; - - //Initialize multiple precision integers - mpiInit(&t); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 64 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 36 / MPI_INT_SIZE)); - - //Perform modular reduction - do - { - //Compute T = A15 | A14 | A13 | A12 | A11 | A10 | A9 | A8 | 0 - CLEAR_WORD32(&t, 0, 1); - COPY_WORD32(&t, 1, a, 8, 8); - - //Clear A15 | A14 | A13 | A12 | A11 | A10 | A9 | A8 - CLEAR_WORD32(a, 8, 8); - - //Compute A = A + T - MPI_CHECK(mpiAdd(a, a, &t)); - //Compute T = T >> 32 - MPI_CHECK(mpiShiftRight(&t, 32)); - //Compute A = A + (977 * T) - MPI_CHECK(mpiMulInt(&t, &t, 977)); - MPI_CHECK(mpiAdd(a, a, &t)); - - //Check for end condition - } while(mpiComp(a, p) > 0); - -end: - //Release multiple precision integers - mpiFree(&t); - - //Return status code - return error; -} - -#endif -#if (SECP256R1_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (secp256r1 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t secp256r1Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi s; - Mpi t; - Mpi b; - - //Initialize multiple precision integers - mpiInit(&s); - mpiInit(&t); - mpiInit(&b); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 64 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&s, 32 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 32 / MPI_INT_SIZE)); - - //Compute T = A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 - COPY_WORD32(&t, 0, a, 0, 8); - - //Compute S1 = A15 | A14 | A13 | A12 | A11 | 0 | 0 | 0 - CLEAR_WORD32(&s, 0, 3); - COPY_WORD32(&s, 3, a, 11, 5); - //Compute T = T + 2 * S1 - MPI_CHECK(mpiAdd(&t, &t, &s)); - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S2 = 0 | A15 | A14 | A13 | A12 | 0 | 0 | 0 - CLEAR_WORD32(&s, 0, 3); - COPY_WORD32(&s, 3, a, 12, 4); - CLEAR_WORD32(&s, 7, 1); - //Compute T = T + 2 * S2 - MPI_CHECK(mpiAdd(&t, &t, &s)); - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S3 = A15 | A14 | 0 | 0 | 0 | A10 | A9 | A8 - COPY_WORD32(&s, 0, a, 8, 3); - CLEAR_WORD32(&s, 3, 3); - COPY_WORD32(&s, 6, a, 14, 2); - //Compute T = T + S3 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S4 = A8 | A13 | A15 | A14 | A13 | A11 | A10 | A9 - COPY_WORD32(&s, 0, a, 9, 3); - COPY_WORD32(&s, 3, a, 13, 3); - COPY_WORD32(&s, 6, a, 13, 1); - COPY_WORD32(&s, 7, a, 8, 1); - //Compute T = T + S4 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute D1 = A10 | A8 | 0 | 0 | 0 | A13 | A12 | A11 - COPY_WORD32(&s, 0, a, 11, 3); - CLEAR_WORD32(&s, 3, 3); - COPY_WORD32(&s, 6, a, 8, 1); - COPY_WORD32(&s, 7, a, 10, 1); - //Compute T = T - D1 - MPI_CHECK(mpiSub(&t, &t, &s)); - - //Compute D2 = A11 | A9 | 0 | 0 | A15 | A14 | A13 | A12 - COPY_WORD32(&s, 0, a, 12, 4); - CLEAR_WORD32(&s, 4, 2); - COPY_WORD32(&s, 6, a, 9, 1); - COPY_WORD32(&s, 7, a, 11, 1); - //Compute T = T - D2 - MPI_CHECK(mpiSub(&t, &t, &s)); - - //Compute D3 = A12 | 0 | A10 | A9 | A8 | A15 | A14 | A13 - COPY_WORD32(&s, 0, a, 13, 3); - COPY_WORD32(&s, 3, a, 8, 3); - CLEAR_WORD32(&s, 6, 1); - COPY_WORD32(&s, 7, a, 12, 1); - //Compute T = T - D3 - MPI_CHECK(mpiSub(&t, &t, &s)); - - //Compute D4 = A13 | 0 | A11 | A10 | A9 | 0 | A15 | A14 - COPY_WORD32(&s, 0, a, 14, 2); - CLEAR_WORD32(&s, 2, 1); - COPY_WORD32(&s, 3, a, 9, 3); - CLEAR_WORD32(&s, 6, 1); - COPY_WORD32(&s, 7, a, 13, 1); - //Compute T = T - D4 - MPI_CHECK(mpiSub(&t, &t, &s)); - - //Compute (T + 2 * S1 + 2 * S2 + S3 + S4 - D1 - D2 - D3 - D4) mod p - while(mpiComp(&t, p) >= 0) - { - MPI_CHECK(mpiSub(&t, &t, p)); - } - - while(mpiCompInt(&t, 0) < 0) - { - MPI_CHECK(mpiAdd(&t, &t, p)); - } - - //Save result - MPI_CHECK(mpiCopy(a, &t)); - -end: - //Release multiple precision integers - mpiFree(&s); - mpiFree(&t); - - //Return status code - return error; -} - -#endif -#if (SECP384R1_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (secp384r1 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t secp384r1Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi s; - Mpi t; - - //Initialize multiple precision integers - mpiInit(&s); - mpiInit(&t); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 96 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&s, 48 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 48 / MPI_INT_SIZE)); - - //Compute T = A11 | A10 | A9 | A8 | A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 - COPY_WORD32(&t, 0, a, 0, 12); - - //Compute S1 = 0 | 0 | 0 | 0 | 0 | A23 | A22 | A21 | 0 | 0 | 0 | 0 - CLEAR_WORD32(&s, 0, 4); - COPY_WORD32(&s, 4, a, 21, 3); - CLEAR_WORD32(&s, 7, 5); - //Compute T = T + 2 * S1 - MPI_CHECK(mpiAdd(&t, &t, &s)); - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S2 = A23 | A22 | A21 | A20 | A19 | A18 | A17 | A16 | A15 | A14 | A13 | A12 - COPY_WORD32(&s, 0, a, 12, 12); - //Compute T = T + S2 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S3 = A20 | A19 | A18 | A17 | A16 | A15 | A14 | A13 | A12 | A23 | A22 | A21 - COPY_WORD32(&s, 0, a, 21, 3); - COPY_WORD32(&s, 3, a, 12, 9); - //Compute T = T + S3 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S4 = A19 | A18 | A17 | A16 | A15 | A14 | A13 | A12 | A20 | 0 | A23 | 0 - CLEAR_WORD32(&s, 0, 1); - COPY_WORD32(&s, 1, a, 23, 1); - CLEAR_WORD32(&s, 2, 1); - COPY_WORD32(&s, 3, a, 20, 1); - COPY_WORD32(&s, 4, a, 12, 8); - //Compute T = T + S4 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S5 = 0 | 0 | 0 | 0 | A23 | A22 | A21 | A20 | 0 | 0 | 0 | 0 - CLEAR_WORD32(&s, 0, 4); - COPY_WORD32(&s, 4, a, 20, 4); - CLEAR_WORD32(&s, 8, 4); - //Compute T = T + S5 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S6 = 0 | 0 | 0 | 0 | 0 | 0 | A23 | A22 | A21 | 0 | 0 | A20 - COPY_WORD32(&s, 0, a, 20, 1); - CLEAR_WORD32(&s, 1, 2); - COPY_WORD32(&s, 3, a, 21, 3); - CLEAR_WORD32(&s, 6, 6); - //Compute T = T + S6 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute D1 = A22 | A21 | A20 | A19 | A18 | A17 | A16 | A15 | A14 | A13 | A12 | A23 - COPY_WORD32(&s, 0, a, 23, 1); - COPY_WORD32(&s, 1, a, 12, 11); - //Compute T = T - D1 - MPI_CHECK(mpiSub(&t, &t, &s)); - - //Compute D2 = 0 | 0 | 0 | 0 | 0 | 0 | 0 | A23 | A22 | A21 | A20 | 0 - CLEAR_WORD32(&s, 0, 1); - COPY_WORD32(&s, 1, a, 20, 4); - CLEAR_WORD32(&s, 5, 7); - //Compute T = T - D2 - MPI_CHECK(mpiSub(&t, &t, &s)); - - //Compute D3 = 0 | 0 | 0 | 0 | 0 | 0 | 0 | A23 | A23 | 0 | 0 | 0 - CLEAR_WORD32(&s, 0, 3); - COPY_WORD32(&s, 3, a, 23, 1); - COPY_WORD32(&s, 4, a, 23, 1); - CLEAR_WORD32(&s, 5, 7); - //Compute T = T - D3 - MPI_CHECK(mpiSub(&t, &t, &s)); - - //Compute (T + 2 * S1 + S2 + S3 + S4 + S5 + S6 - D1 - D2 - D3) mod p - while(mpiComp(&t, p) >= 0) - { - MPI_CHECK(mpiSub(&t, &t, p)); - } - - while(mpiCompInt(&t, 0) < 0) - { - MPI_CHECK(mpiAdd(&t, &t, p)); - } - - //Save result - MPI_CHECK(mpiCopy(a, &t)); - -end: - //Release multiple precision integers - mpiFree(&s); - mpiFree(&t); - - //Return status code - return error; -} - -#endif -#if (SECP521R1_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (secp521r1 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t secp521r1Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi t; - - //Initialize multiple precision integer - mpiInit(&t); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 132 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 68 / MPI_INT_SIZE)); - - //Compute A0 - COPY_WORD32(&t, 0, a, 0, 17); - t.data[16] &= 0x000001FF; - - //Compute A1 - MPI_CHECK(mpiShiftRight(a, 521)); - - //Compute A0 + A1 - MPI_CHECK(mpiAdd(a, a, &t)); - - //Compute (A0 + A1) mod p - while(mpiComp(a, p) >= 0) - { - MPI_CHECK(mpiSub(a, a, p)); - } - -end: - //Release multiple precision integer - mpiFree(&t); - - //Return status code - return error; -} - -#endif -#if (SM2_SUPPORT == ENABLED) - -/** - * @brief Fast modular reduction (SM2 curve) - * @param[in,out] a This function accept an integer less than p^2 as - * input and return (a mod p) as output - * @param[in] p Prime modulus - **/ - -error_t sm2Mod(Mpi *a, const Mpi *p) -{ - error_t error; - Mpi s; - Mpi t; - Mpi b; - - //Initialize multiple precision integers - mpiInit(&s); - mpiInit(&t); - mpiInit(&b); - - //Ajust the size of the integers - MPI_CHECK(mpiGrow(a, 64 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&s, 32 / MPI_INT_SIZE)); - MPI_CHECK(mpiGrow(&t, 32 / MPI_INT_SIZE)); - - //Compute T = A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 - COPY_WORD32(&t, 0, a, 0, 8); - - //Compute S1 = A15 | A14 | A13 | A12 | A11 | 0 | A9 | A8 - COPY_WORD32(&s, 0, a, 8, 2); - CLEAR_WORD32(&s, 2, 1); - COPY_WORD32(&s, 3, a, 11, 5); - //Compute T = T + S1 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S2 = A8 | A15 | A14 | A13 | A12 | 0 | A10 | A9 - COPY_WORD32(&s, 0, a, 9, 2); - CLEAR_WORD32(&s, 2, 1); - COPY_WORD32(&s, 3, a, 12, 4); - COPY_WORD32(&s, 7, a, 8, 1); - //Compute T = T + S2 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S3 = A9 | A11 | A10 | A9 | A8 | 0 | A11 | A10 - COPY_WORD32(&s, 0, a, 10, 2); - CLEAR_WORD32(&s, 2, 1); - COPY_WORD32(&s, 3, a, 8, 4); - COPY_WORD32(&s, 7, a, 9, 1); - //Compute T = T + S3 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S4 = A10 | 0 | 0 | A15 | A14 | 0 | A12 | A11 - COPY_WORD32(&s, 0, a, 11, 2); - CLEAR_WORD32(&s, 2, 1); - COPY_WORD32(&s, 3, a, 14, 2); - CLEAR_WORD32(&s, 5, 2); - COPY_WORD32(&s, 7, a, 10, 1); - //Compute T = T + S4 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S5 = A11 | 0 | 0 | 0 | A15 | 0 | A13 | A12 - COPY_WORD32(&s, 0, a, 12, 2); - CLEAR_WORD32(&s, 2, 1); - COPY_WORD32(&s, 3, a, 15, 1); - CLEAR_WORD32(&s, 4, 3); - COPY_WORD32(&s, 7, a, 11, 1); - //Compute T = T + S5 - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S6 = A12 | 0 | A15 | A14 | A13 | 0 | A14 | A13 - COPY_WORD32(&s, 0, a, 13, 2); - CLEAR_WORD32(&s, 2, 1); - COPY_WORD32(&s, 3, a, 13, 3); - CLEAR_WORD32(&s, 6, 1); - COPY_WORD32(&s, 7, a, 12, 1); - //Compute T = T + 2*S6 - MPI_CHECK(mpiAdd(&t, &t, &s)); - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S7 = A13 | 0 | 0 | 0 | 0 | 0 | A15 | A14 - COPY_WORD32(&s, 0, a, 14, 2); - CLEAR_WORD32(&s, 2, 5); - COPY_WORD32(&s, 7, a, 13, 1); - //Compute T = T + 2*S7 - MPI_CHECK(mpiAdd(&t, &t, &s)); - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S8 = A14 | 0 | 0 | 0 | 0 | 0 | 0 | A15 - COPY_WORD32(&s, 0, a, 15, 1); - CLEAR_WORD32(&s, 1, 6); - COPY_WORD32(&s, 7, a, 14, 1); - //Compute T = T + 2*S8 - MPI_CHECK(mpiAdd(&t, &t, &s)); - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute S9 = A15 | 0 | 0 | 0 | 0 | 0 | 0 | 0 - CLEAR_WORD32(&s, 0, 7); - COPY_WORD32(&s, 7, a, 15, 1); - //Compute T = T + 2*S9 - MPI_CHECK(mpiAdd(&t, &t, &s)); - MPI_CHECK(mpiAdd(&t, &t, &s)); - - //Compute D1 = 0 | 0 | 0 | 0 | 0 | A8 | 0 | 0 - CLEAR_WORD32(&s, 0, 2); - COPY_WORD32(&s, 2, a, 8, 1); - CLEAR_WORD32(&s, 3, 5); - //Compute T = T - D1 - MPI_CHECK(mpiSub(&t, &t, &s)); - - //Compute D2 = 0 | 0 | 0 | 0 | 0 | A9 | 0 | 0 - CLEAR_WORD32(&s, 0, 2); - COPY_WORD32(&s, 2, a, 9, 1); - CLEAR_WORD32(&s, 3, 5); - //Compute T = T - D2 - MPI_CHECK(mpiSub(&t, &t, &s)); - - //Compute D3 = 0 | 0 | 0 | 0 | 0 | A13 | 0 | 0 - CLEAR_WORD32(&s, 0, 2); - COPY_WORD32(&s, 2, a, 13, 1); - CLEAR_WORD32(&s, 3, 5); - //Compute T = T - D3 - MPI_CHECK(mpiSub(&t, &t, &s)); - - //Compute D4 = 0 | 0 | 0 | 0 | 0 | A14 | 0 | 0 - CLEAR_WORD32(&s, 0, 2); - COPY_WORD32(&s, 2, a, 14, 1); - CLEAR_WORD32(&s, 3, 5); - //Compute T = T - D4 - MPI_CHECK(mpiSub(&t, &t, &s)); - - //Compute (T + S1 + S2 + S3 + S4 + S5 + 2*S6 + 2*S7 + 2*S8 + 2*S9 - D1 - D2 - D3 - D4) mod p - while(mpiComp(&t, p) >= 0) - { - MPI_CHECK(mpiSub(&t, &t, p)); - } - - while(mpiCompInt(&t, 0) < 0) - { - MPI_CHECK(mpiAdd(&t, &t, p)); - } - - //Save result - MPI_CHECK(mpiCopy(a, &t)); - -end: - //Release multiple precision integers - mpiFree(&s); - mpiFree(&t); - - //Return status code - return error; -} - -#endif - -/** - * @brief Get the elliptic curve that matches the specified OID - * @param[in] oid Object identifier - * @param[in] length OID length - * @return Elliptic curve domain parameters - **/ - -const EcCurveInfo *ecGetCurveInfo(const uint8_t *oid, size_t length) -{ - const EcCurveInfo *curveInfo; - - //Invalid parameters? - if(oid == NULL || length == 0) - { - curveInfo = NULL; - } -#if (SECP112R1_SUPPORT == ENABLED) - //secp112r1 elliptic curve? - else if(!oidComp(oid, length, SECP112R1_OID, sizeof(SECP112R1_OID))) - { - curveInfo = SECP112R1_CURVE; - } -#endif -#if (SECP112R2_SUPPORT == ENABLED) - //secp112r2 elliptic curve? - else if(!oidComp(oid, length, SECP112R2_OID, sizeof(SECP112R2_OID))) - { - curveInfo = SECP112R2_CURVE; - } -#endif -#if (SECP128R1_SUPPORT == ENABLED) - //secp128r1 elliptic curve? - else if(!oidComp(oid, length, SECP128R1_OID, sizeof(SECP128R1_OID))) - { - curveInfo = SECP128R1_CURVE; - } -#endif -#if (SECP128R2_SUPPORT == ENABLED) - //secp128r2 elliptic curve? - else if(!oidComp(oid, length, SECP128R2_OID, sizeof(SECP128R2_OID))) - { - curveInfo = SECP128R2_CURVE; - } -#endif -#if (SECP160K1_SUPPORT == ENABLED) - //secp160k1 elliptic curve? - else if(!oidComp(oid, length, SECP160K1_OID, sizeof(SECP160K1_OID))) - { - curveInfo = SECP160K1_CURVE; - } -#endif -#if (SECP160R1_SUPPORT == ENABLED) - //secp160r1 elliptic curve? - else if(!oidComp(oid, length, SECP160R1_OID, sizeof(SECP160R1_OID))) - { - curveInfo = SECP160R1_CURVE; - } -#endif -#if (SECP160R2_SUPPORT == ENABLED) - //secp160r2 elliptic curve? - else if(!oidComp(oid, length, SECP160R2_OID, sizeof(SECP160R2_OID))) - { - curveInfo = SECP160R2_CURVE; - } -#endif -#if (SECP192K1_SUPPORT == ENABLED) - //secp192k1 elliptic curve? - else if(!oidComp(oid, length, SECP192K1_OID, sizeof(SECP192K1_OID))) - { - curveInfo = SECP192K1_CURVE; - } -#endif -#if (SECP192R1_SUPPORT == ENABLED) - //secp192r1 elliptic curve? - else if(!oidComp(oid, length, SECP192R1_OID, sizeof(SECP192R1_OID))) - { - curveInfo = SECP192R1_CURVE; - } -#endif -#if (SECP224K1_SUPPORT == ENABLED) - //secp224k1 elliptic curve? - else if(!oidComp(oid, length, SECP224K1_OID, sizeof(SECP224K1_OID))) - { - curveInfo = SECP224K1_CURVE; - } -#endif -#if (SECP224R1_SUPPORT == ENABLED) - //secp224r1 elliptic curve? - else if(!oidComp(oid, length, SECP224R1_OID, sizeof(SECP224R1_OID))) - { - curveInfo = SECP224R1_CURVE; - } -#endif -#if (SECP256K1_SUPPORT == ENABLED) - //secp256k1 elliptic curve? - else if(!oidComp(oid, length, SECP256K1_OID, sizeof(SECP256K1_OID))) - { - curveInfo = SECP256K1_CURVE; - } -#endif -#if (SECP256R1_SUPPORT == ENABLED) - //secp256r1 elliptic curve? - else if(!oidComp(oid, length, SECP256R1_OID, sizeof(SECP256R1_OID))) - { - curveInfo = SECP256R1_CURVE; - } -#endif -#if (SECP384R1_SUPPORT == ENABLED) - //secp384r1 elliptic curve? - else if(!oidComp(oid, length, SECP384R1_OID, sizeof(SECP384R1_OID))) - { - curveInfo = SECP384R1_CURVE; - } -#endif -#if (SECP521R1_SUPPORT == ENABLED) - //secp521r1 elliptic curve? - else if(!oidComp(oid, length, SECP521R1_OID, sizeof(SECP521R1_OID))) - { - curveInfo = SECP521R1_CURVE; - } -#endif -#if (BRAINPOOLP160R1_SUPPORT == ENABLED) - //brainpoolP160r1 elliptic curve? - else if(!oidComp(oid, length, BRAINPOOLP160R1_OID, sizeof(BRAINPOOLP160R1_OID))) - { - curveInfo = BRAINPOOLP160R1_CURVE; - } -#endif -#if (BRAINPOOLP192R1_SUPPORT == ENABLED) - //brainpoolP192r1 elliptic curve? - else if(!oidComp(oid, length, BRAINPOOLP192R1_OID, sizeof(BRAINPOOLP192R1_OID))) - { - curveInfo = BRAINPOOLP192R1_CURVE; - } -#endif -#if (BRAINPOOLP224R1_SUPPORT == ENABLED) - //brainpoolP224r1 elliptic curve? - else if(!oidComp(oid, length, BRAINPOOLP224R1_OID, sizeof(BRAINPOOLP224R1_OID))) - { - curveInfo = BRAINPOOLP224R1_CURVE; - } -#endif -#if (BRAINPOOLP256R1_SUPPORT == ENABLED) - //brainpoolP256r1 elliptic curve? - else if(!oidComp(oid, length, BRAINPOOLP256R1_OID, sizeof(BRAINPOOLP256R1_OID))) - { - curveInfo = BRAINPOOLP256R1_CURVE; - } -#endif -#if (BRAINPOOLP320R1_SUPPORT == ENABLED) - //brainpoolP320r1 elliptic curve? - else if(!oidComp(oid, length, BRAINPOOLP320R1_OID, sizeof(BRAINPOOLP320R1_OID))) - { - curveInfo = BRAINPOOLP320R1_CURVE; - } -#endif -#if (BRAINPOOLP384R1_SUPPORT == ENABLED) - //brainpoolP384r1 elliptic curve? - else if(!oidComp(oid, length, BRAINPOOLP384R1_OID, sizeof(BRAINPOOLP384R1_OID))) - { - curveInfo = BRAINPOOLP384R1_CURVE; - } -#endif -#if (BRAINPOOLP512R1_SUPPORT == ENABLED) - //brainpoolP512r1 elliptic curve? - else if(!oidComp(oid, length, BRAINPOOLP512R1_OID, sizeof(BRAINPOOLP512R1_OID))) - { - curveInfo = BRAINPOOLP512R1_CURVE; - } -#endif -#if (SM2_SUPPORT == ENABLED) - //SM2 elliptic curve? - else if(!oidComp(oid, length, SM2_OID, sizeof(SM2_OID))) - { - curveInfo = SM2_CURVE; - } -#endif -#if (X25519_SUPPORT == ENABLED) - //Curve25519 elliptic curve? - else if(!oidComp(oid, length, X25519_OID, sizeof(X25519_OID))) - { - curveInfo = X25519_CURVE; - } -#endif -#if (X448_SUPPORT == ENABLED) - //Curve448 elliptic curve? - else if(!oidComp(oid, length, X448_OID, sizeof(X448_OID))) - { - curveInfo = X448_CURVE; - } -#endif -#if (ED25519_SUPPORT == ENABLED) - //Ed25519 elliptic curve? - else if(!oidComp(oid, length, ED25519_OID, sizeof(ED25519_OID))) - { - curveInfo = ED25519_CURVE; - } -#endif -#if (ED448_SUPPORT == ENABLED) - //Ed448 elliptic curve? - else if(!oidComp(oid, length, ED448_OID, sizeof(ED448_OID))) - { - curveInfo = ED448_CURVE; - } -#endif - //Unknown identifier? - else - { - curveInfo = NULL; - } - - //Return the elliptic curve domain parameters, if any - return curveInfo; -} - -#endif +/** + * @file ec_curves.c + * @brief Elliptic curves + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * Copyright (c) 2024 Valery Novikov + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded SARL (www.oryx-embedded.com) + * @version 2.4.0 + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL CRYPTO_TRACE_LEVEL + +//Dependencies +#include "core/crypto.h" +#include "ecc/ec_curves.h" +#include "encoding/oid.h" +#include "debug.h" + +//Check crypto library configuration +#if (EC_SUPPORT == ENABLED) + +//Macro definition +#define CLEAR_WORD32(a, i, n) osMemset((a)->data + i, 0, n * MPI_INT_SIZE); +#define COPY_WORD32(a, i, b, j, n) osMemcpy((a)->data + i, (b)->data + j, n * MPI_INT_SIZE); + +//secp112r1 OID (1.3.132.0.6) +const uint8_t SECP112R1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x06}; +//secp112r2 OID (1.3.132.0.7) +const uint8_t SECP112R2_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x07}; +//secp128r1 OID (1.3.132.0.28) +const uint8_t SECP128R1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x1C}; +//secp128r2 OID (1.3.132.0.29) +const uint8_t SECP128R2_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x1D}; +//secp160k1 OID (1.3.132.0.9) +const uint8_t SECP160K1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x09}; +//secp160r1 OID (1.3.132.0.8) +const uint8_t SECP160R1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x08}; +//secp160r2 OID (1.3.132.0.30) +const uint8_t SECP160R2_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x1E}; +//secp192k1 OID (1.3.132.0.31) +const uint8_t SECP192K1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x1F}; +//secp192r1 OID (1.2.840.10045.3.1.1) +const uint8_t SECP192R1_OID[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x01}; +//secp224k1 OID (1.3.132.0.32) +const uint8_t SECP224K1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x20}; +//secp224r1 OID (1.3.132.0.33) +const uint8_t SECP224R1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x21}; +//secp256k1 OID (1.3.132.0.10) +const uint8_t SECP256K1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x0A}; +//secp256r1 OID (1.2.840.10045.3.1.7) +const uint8_t SECP256R1_OID[8] = {0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}; +//secp384r1 OID (1.3.132.0.34) +const uint8_t SECP384R1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x22}; +//secp521r1 OID (1.3.132.0.35) +const uint8_t SECP521R1_OID[5] = {0x2B, 0x81, 0x04, 0x00, 0x23}; +//brainpoolP160r1 OID (1.3.36.3.3.2.8.1.1.1) +const uint8_t BRAINPOOLP160R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x01}; +//brainpoolP192r1 OID (1.3.36.3.3.2.8.1.1.3) +const uint8_t BRAINPOOLP192R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x03}; +//brainpoolP224r1 OID (1.3.36.3.3.2.8.1.1.5) +const uint8_t BRAINPOOLP224R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x05}; +//brainpoolP256r1 OID (1.3.36.3.3.2.8.1.1.7) +const uint8_t BRAINPOOLP256R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}; +//brainpoolP320r1 OID (1.3.36.3.3.2.8.1.1.9) +const uint8_t BRAINPOOLP320R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x09}; +//brainpoolP384r1 OID (1.3.36.3.3.2.8.1.1.11) +const uint8_t BRAINPOOLP384R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}; +//brainpoolP512r1 OID (1.3.36.3.3.2.8.1.1.13) +const uint8_t BRAINPOOLP512R1_OID[9] = {0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}; +//SM2 OID (1.2.156.10197.1.301) +const uint8_t SM2_OID[8] = {0x2A, 0x81, 0x1C, 0xCF, 0x55, 0x01, 0x82, 0x2D}; +//X25519 OID (1.3.101.110) +const uint8_t X25519_OID[3] = {0x2B, 0x65, 0x6E}; +//X448 OID (1.3.101.111) +const uint8_t X448_OID[3] = {0x2B, 0x65, 0x6F}; +//Ed25519 OID (1.3.101.112) +const uint8_t ED25519_OID[3] = {0x2B, 0x65, 0x70}; +//Ed448 OID (1.3.101.113) +const uint8_t ED448_OID[3] = {0x2B, 0x65, 0x71}; +//tc26Sign512a OID (1.2.643.7.1.2.1.2.1) +const uint8_t TC26SIGN512A_OID[9] = {0x2A, 0x85, 0x03, 0x07, 0x01, 0x02, 0x01, 0x02, 0x01}; +//tc26Sign512b OID (1.2.643.7.1.2.1.2.2) +const uint8_t TC26SIGN512B_OID[9] = {0x2A, 0x85, 0x03, 0x07, 0x01, 0x02, 0x01, 0x02, 0x02}; + + +#if (SECP112R1_SUPPORT == ENABLED) + +/** + * @brief secp112r1 elliptic curve + **/ + +const EcCurveInfo secp112r1Curve = +{ + //Curve name + "secp112r1", + //Object identifier + SECP112R1_OID, + sizeof(SECP112R1_OID), + //Curve type + EC_CURVE_TYPE_SECP_R1, + //Prime modulus p + {0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x66, 0x80, 0x76, 0xBE, 0xAD, 0x20, 0x8B}, + 14, + //Curve parameter a + {0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x66, 0x80, 0x76, 0xBE, 0xAD, 0x20, 0x88}, + 14, + //Curve parameter b + {0x65, 0x9E, 0xF8, 0xBA, 0x04, 0x39, 0x16, 0xEE, 0xDE, 0x89, 0x11, 0x70, 0x2B, 0x22}, + 14, + //x-coordinate of the base point G + {0x09, 0x48, 0x72, 0x39, 0x99, 0x5A, 0x5E, 0xE7, 0x6B, 0x55, 0xF9, 0xC2, 0xF0, 0x98}, + 14, + //y-coordinate of the base point G + {0xA8, 0x9C, 0xE5, 0xAF, 0x87, 0x24, 0xC0, 0xA2, 0x3E, 0x0E, 0x0F, 0xF7, 0x75, 0x00}, + 14, + //Base point order q + {0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x76, 0x28, 0xDF, 0xAC, 0x65, 0x61, 0xC5}, + 14, + //Cofactor + 1, + //Fast modular reduction + NULL +}; + +#endif +#if (SECP112R2_SUPPORT == ENABLED) + +/** + * @brief secp112r2 elliptic curve + **/ + +const EcCurveInfo secp112r2Curve = +{ + //Curve name + "secp112r2", + //Object identifier + SECP112R2_OID, + sizeof(SECP112R2_OID), + //Curve type + EC_CURVE_TYPE_SECP_R2, + //Prime modulus p + {0xDB, 0x7C, 0x2A, 0xBF, 0x62, 0xE3, 0x5E, 0x66, 0x80, 0x76, 0xBE, 0xAD, 0x20, 0x8B}, + 14, + //Curve parameter a + {0x61, 0x27, 0xC2, 0x4C, 0x05, 0xF3, 0x8A, 0x0A, 0xAA, 0xF6, 0x5C, 0x0E, 0xF0, 0x2C}, + 14, + //Curve parameter b + {0x51, 0xDE, 0xF1, 0x81, 0x5D, 0xB5, 0xED, 0x74, 0xFC, 0xC3, 0x4C, 0x85, 0xD7, 0x09}, + 14, + //x-coordinate of the base point G + {0x4B, 0xA3, 0x0A, 0xB5, 0xE8, 0x92, 0xB4, 0xE1, 0x64, 0x9D, 0xD0, 0x92, 0x86, 0x43}, + 14, + //y-coordinate of the base point G + {0xAD, 0xCD, 0x46, 0xF5, 0x88, 0x2E, 0x37, 0x47, 0xDE, 0xF3, 0x6E, 0x95, 0x6E, 0x97}, + 14, + //Base point order q + {0x36, 0xDF, 0x0A, 0xAF, 0xD8, 0xB8, 0xD7, 0x59, 0x7C, 0xA1, 0x05, 0x20, 0xD0, 0x4B}, + 14, + //Cofactor + 4, + //Fast modular reduction + NULL +}; + +#endif +#if (SECP128R1_SUPPORT == ENABLED) + +/** + * @brief secp128r1 elliptic curve + **/ + +const EcCurveInfo secp128r1Curve = +{ + //Curve name + "secp128r1", + //Object identifier + SECP128R1_OID, + sizeof(SECP128R1_OID), + //Curve type + EC_CURVE_TYPE_SECP_R1, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + 16, + //Curve parameter a + {0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}, + 16, + //Curve parameter b + {0xE8, 0x75, 0x79, 0xC1, 0x10, 0x79, 0xF4, 0x3D, 0xD8, 0x24, 0x99, 0x3C, 0x2C, 0xEE, 0x5E, 0xD3}, + 16, + //x-coordinate of the base point G + {0x16, 0x1F, 0xF7, 0x52, 0x8B, 0x89, 0x9B, 0x2D, 0x0C, 0x28, 0x60, 0x7C, 0xA5, 0x2C, 0x5B, 0x86}, + 16, + //y-coordinate of the base point G + {0xCF, 0x5A, 0xC8, 0x39, 0x5B, 0xAF, 0xEB, 0x13, 0xC0, 0x2D, 0xA2, 0x92, 0xDD, 0xED, 0x7A, 0x83}, + 16, + //Base point order q + {0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x75, 0xA3, 0x0D, 0x1B, 0x90, 0x38, 0xA1, 0x15}, + 16, + //Cofactor + 1, + //Fast modular reduction + secp128r1Mod +}; + +#endif +#if (SECP128R2_SUPPORT == ENABLED) + +/** + * @brief secp128r2 elliptic curve + **/ + +const EcCurveInfo secp128r2Curve = +{ + //Curve name + "secp128r2", + //Object identifier + SECP128R2_OID, + sizeof(SECP128R2_OID), + //Curve type + EC_CURVE_TYPE_SECP_R2, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + 16, + //Curve parameter a + {0xD6, 0x03, 0x19, 0x98, 0xD1, 0xB3, 0xBB, 0xFE, 0xBF, 0x59, 0xCC, 0x9B, 0xBF, 0xF9, 0xAE, 0xE1}, + 16, + //Curve parameter b + {0x5E, 0xEE, 0xFC, 0xA3, 0x80, 0xD0, 0x29, 0x19, 0xDC, 0x2C, 0x65, 0x58, 0xBB, 0x6D, 0x8A, 0x5D}, + 16, + //x-coordinate of the base point G + {0x7B, 0x6A, 0xA5, 0xD8, 0x5E, 0x57, 0x29, 0x83, 0xE6, 0xFB, 0x32, 0xA7, 0xCD, 0xEB, 0xC1, 0x40}, + 16, + //y-coordinate of the base point G + {0x27, 0xB6, 0x91, 0x6A, 0x89, 0x4D, 0x3A, 0xEE, 0x71, 0x06, 0xFE, 0x80, 0x5F, 0xC3, 0x4B, 0x44}, + 16, + //Base point order q + {0x3F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xBE, 0x00, 0x24, 0x72, 0x06, 0x13, 0xB5, 0xA3}, + 16, + //Cofactor + 4, + //Fast modular reduction + secp128r2Mod +}; + +#endif +#if (SECP160K1_SUPPORT == ENABLED) + +/** + * @brief secp160k1 elliptic curve + **/ + +const EcCurveInfo secp160k1Curve = +{ + //Curve name + "secp160k1", + //Object identifier + SECP160K1_OID, + sizeof(SECP160K1_OID), + //Curve type + EC_CURVE_TYPE_SECP_K1, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xAC, 0x73}, + 20, + //Curve parameter a + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}, + 20, + //Curve parameter b + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07}, + 20, + //x-coordinate of the base point G + {0x3B, 0x4C, 0x38, 0x2C, 0xE3, 0x7A, 0xA1, 0x92, 0xA4, 0x01, 0x9E, 0x76, 0x30, 0x36, 0xF4, 0xF5, + 0xDD, 0x4D, 0x7E, 0xBB}, + 20, + //y-coordinate of the base point G + {0x93, 0x8C, 0xF9, 0x35, 0x31, 0x8F, 0xDC, 0xED, 0x6B, 0xC2, 0x82, 0x86, 0x53, 0x17, 0x33, 0xC3, + 0xF0, 0x3C, 0x4F, 0xEE}, + 20, + //Base point order q + {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xB8, 0xFA, 0x16, 0xDF, 0xAB, + 0x9A, 0xCA, 0x16, 0xB6, 0xB3}, + 21, + //Cofactor + 1, + //Fast modular reduction + secp160k1Mod +}; + +#endif +#if (SECP160R1_SUPPORT == ENABLED) + +/** + * @brief secp160r1 elliptic curve + **/ + +const EcCurveInfo secp160r1Curve = +{ + //Curve name + "secp160r1", + //Object identifier + SECP160R1_OID, + sizeof(SECP160R1_OID), + //Curve type + EC_CURVE_TYPE_SECP_R1, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFF}, + 20, + //Curve parameter a + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x7F, 0xFF, 0xFF, 0xFC}, + 20, + //Curve parameter b + {0x1C, 0x97, 0xBE, 0xFC, 0x54, 0xBD, 0x7A, 0x8B, 0x65, 0xAC, 0xF8, 0x9F, 0x81, 0xD4, 0xD4, 0xAD, + 0xC5, 0x65, 0xFA, 0x45}, + 20, + //x-coordinate of the base point G + {0x4A, 0x96, 0xB5, 0x68, 0x8E, 0xF5, 0x73, 0x28, 0x46, 0x64, 0x69, 0x89, 0x68, 0xC3, 0x8B, 0xB9, + 0x13, 0xCB, 0xFC, 0x82}, + 20, + //y-coordinate of the base point G + {0x23, 0xA6, 0x28, 0x55, 0x31, 0x68, 0x94, 0x7D, 0x59, 0xDC, 0xC9, 0x12, 0x04, 0x23, 0x51, 0x37, + 0x7A, 0xC5, 0xFB, 0x32}, + 20, + //Base point order q + {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF4, 0xC8, 0xF9, 0x27, 0xAE, + 0xD3, 0xCA, 0x75, 0x22, 0x57}, + 21, + //Cofactor + 1, + //Fast modular reduction + secp160r1Mod +}; + +#endif +#if (SECP160R2_SUPPORT == ENABLED) + +/** + * @brief secp160r2 elliptic curve + **/ + +const EcCurveInfo secp160r2Curve = +{ + //Curve name + "secp160r2", + //Object identifier + SECP160R2_OID, + sizeof(SECP160R2_OID), + //Curve type + EC_CURVE_TYPE_SECP_R2, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xAC, 0x73}, + 20, + //Curve parameter a + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xAC, 0x70}, + 20, + //Curve parameter b + {0xB4, 0xE1, 0x34, 0xD3, 0xFB, 0x59, 0xEB, 0x8B, 0xAB, 0x57, 0x27, 0x49, 0x04, 0x66, 0x4D, 0x5A, + 0xF5, 0x03, 0x88, 0xBA}, + 20, + //x-coordinate of the base point G + {0x52, 0xDC, 0xB0, 0x34, 0x29, 0x3A, 0x11, 0x7E, 0x1F, 0x4F, 0xF1, 0x1B, 0x30, 0xF7, 0x19, 0x9D, + 0x31, 0x44, 0xCE, 0x6D}, + 20, + //y-coordinate of the base point G + {0xFE, 0xAF, 0xFE, 0xF2, 0xE3, 0x31, 0xF2, 0x96, 0xE0, 0x71, 0xFA, 0x0D, 0xF9, 0x98, 0x2C, 0xFE, + 0xA7, 0xD4, 0x3F, 0x2E}, + 20, + //Base point order q + {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x1E, 0xE7, 0x86, 0xA8, + 0x18, 0xF3, 0xA1, 0xA1, 0x6B}, + 21, + //Cofactor + 1, + //Fast modular reduction + secp160r2Mod +}; + +#endif +#if (SECP192K1_SUPPORT == ENABLED) + +/** + * @brief secp192k1 elliptic curve + **/ + +const EcCurveInfo secp192k1Curve = +{ + //Curve name + "secp192k1", + //Object identifier + SECP192K1_OID, + sizeof(SECP192K1_OID), + //Curve type + EC_CURVE_TYPE_SECP_K1, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEE, 0x37}, + 24, + //Curve parameter a + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + 24, + //Curve parameter b + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + 24, + //x-coordinate of the base point G + {0xDB, 0x4F, 0xF1, 0x0E, 0xC0, 0x57, 0xE9, 0xAE, 0x26, 0xB0, 0x7D, 0x02, 0x80, 0xB7, 0xF4, 0x34, + 0x1D, 0xA5, 0xD1, 0xB1, 0xEA, 0xE0, 0x6C, 0x7D}, + 24, + //y-coordinate of the base point G + {0x9B, 0x2F, 0x2F, 0x6D, 0x9C, 0x56, 0x28, 0xA7, 0x84, 0x41, 0x63, 0xD0, 0x15, 0xBE, 0x86, 0x34, + 0x40, 0x82, 0xAA, 0x88, 0xD9, 0x5E, 0x2F, 0x9D}, + 24, + //Base point order q + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x26, 0xF2, 0xFC, 0x17, + 0x0F, 0x69, 0x46, 0x6A, 0x74, 0xDE, 0xFD, 0x8D}, + 24, + //Cofactor + 1, + //Fast modular reduction + secp192k1Mod +}; + +#endif +#if (SECP192R1_SUPPORT == ENABLED) + +/** + * @brief secp192r1 elliptic curve + **/ + +const EcCurveInfo secp192r1Curve = +{ + //Curve name + "secp192r1", + //Object identifier + SECP192R1_OID, + sizeof(SECP192R1_OID), + //Curve type + EC_CURVE_TYPE_SECP_R1, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + 24, + //Curve parameter a + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}, + 24, + //Curve parameter b + {0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7, 0x0F, 0xA7, 0xE9, 0xAB, 0x72, 0x24, 0x30, 0x49, + 0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1}, + 24, + //x-coordinate of the base point G + {0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, 0x7C, 0xBF, 0x20, 0xEB, 0x43, 0xA1, 0x88, 0x00, + 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12}, + 24, + //y-coordinate of the base point G + {0x07, 0x19, 0x2B, 0x95, 0xFF, 0xC8, 0xDA, 0x78, 0x63, 0x10, 0x11, 0xED, 0x6B, 0x24, 0xCD, 0xD5, + 0x73, 0xF9, 0x77, 0xA1, 0x1E, 0x79, 0x48, 0x11}, + 24, + //Base point order q + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0xDE, 0xF8, 0x36, + 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31}, + 24, + //Cofactor + 1, + //Fast modular reduction + secp192r1Mod +}; + +#endif +#if (SECP224K1_SUPPORT == ENABLED) + +/** + * @brief secp224k1 elliptic curve + **/ + +const EcCurveInfo secp224k1Curve = +{ + //Curve name + "secp224k1", + //Object identifier + SECP224K1_OID, + sizeof(SECP224K1_OID), + //Curve type + EC_CURVE_TYPE_SECP_K1, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xE5, 0x6D}, + 28, + //Curve parameter a + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + 28, + //Curve parameter b + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + 28, + //x-coordinate of the base point G + {0xA1, 0x45, 0x5B, 0x33, 0x4D, 0xF0, 0x99, 0xDF, 0x30, 0xFC, 0x28, 0xA1, 0x69, 0xA4, 0x67, 0xE9, + 0xE4, 0x70, 0x75, 0xA9, 0x0F, 0x7E, 0x65, 0x0E, 0xB6, 0xB7, 0xA4, 0x5C}, + 28, + //y-coordinate of the base point G + {0x7E, 0x08, 0x9F, 0xED, 0x7F, 0xBA, 0x34, 0x42, 0x82, 0xCA, 0xFB, 0xD6, 0xF7, 0xE3, 0x19, 0xF7, + 0xC0, 0xB0, 0xBD, 0x59, 0xE2, 0xCA, 0x4B, 0xDB, 0x55, 0x6D, 0x61, 0xA5}, + 28, + //Base point order q + {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xDC, + 0xE8, 0xD2, 0xEC, 0x61, 0x84, 0xCA, 0xF0, 0xA9, 0x71, 0x76, 0x9F, 0xB1, 0xF7}, + 29, + //Cofactor + 1, + //Fast modular reduction + secp224k1Mod +}; + +#endif +#if (SECP224R1_SUPPORT == ENABLED) + +/** + * @brief secp224r1 elliptic curve + **/ + +const EcCurveInfo secp224r1Curve = +{ + //Curve name + "secp224r1", + //Object identifier + SECP224R1_OID, + sizeof(SECP224R1_OID), + //Curve type + EC_CURVE_TYPE_SECP_R1, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + 28, + //Curve parameter a + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE}, + 28, + //Curve parameter b + {0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56, 0x50, 0x44, 0xB0, 0xB7, + 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4}, + 28, + //x-coordinate of the base point G + {0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9, 0x4A, 0x03, 0xC1, 0xD3, + 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21}, + 28, + //y-coordinate of the base point G + {0xBD, 0x37, 0x63, 0x88, 0xB5, 0xF7, 0x23, 0xFB, 0x4C, 0x22, 0xDF, 0xE6, 0xCD, 0x43, 0x75, 0xA0, + 0x5A, 0x07, 0x47, 0x64, 0x44, 0xD5, 0x81, 0x99, 0x85, 0x00, 0x7E, 0x34}, + 28, + //Base point order q + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x16, 0xA2, + 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45, 0x5C, 0x5C, 0x2A, 0x3D}, + 28, + //Cofactor + 1, + //Fast modular reduction + secp224r1Mod +}; + +#endif +#if (SECP256K1_SUPPORT == ENABLED) + +/** + * @brief secp256k1 elliptic curve + **/ + +const EcCurveInfo secp256k1Curve = +{ + //Curve name + "secp256k1", + //Object identifier + SECP256K1_OID, + sizeof(SECP256K1_OID), + //Curve type + EC_CURVE_TYPE_SECP_K1, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F}, + 32, + //Curve parameter a + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + 32, + //Curve parameter b + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07}, + 32, + //x-coordinate of the base point G + {0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, + 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98}, + 32, + //y-coordinate of the base point G + {0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65, 0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, 0xA8, + 0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19, 0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, 0xB8}, + 32, + //Base point order q + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41}, + 32, + //Cofactor + 1, + //Fast modular reduction + secp256k1Mod +}; + +#endif +#if (SECP256R1_SUPPORT == ENABLED) + +/** + * @brief secp256r1 elliptic curve + **/ + +const EcCurveInfo secp256r1Curve = +{ + //Curve name + "secp256r1", + //Object identifier + SECP256R1_OID, + sizeof(SECP256R1_OID), + //Curve type + EC_CURVE_TYPE_SECP_R1, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + 32, + //Curve parameter a + {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}, + 32, + //Curve parameter b + {0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55, 0x76, 0x98, 0x86, 0xBC, + 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6, 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B}, + 32, + //x-coordinate of the base point G + {0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5, 0x63, 0xA4, 0x40, 0xF2, + 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0, 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96}, + 32, + //y-coordinate of the base point G + {0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A, 0x7C, 0x0F, 0x9E, 0x16, + 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE, 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5}, + 32, + //Base point order q + {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51}, + 32, + //Cofactor + 1, + //Fast modular reduction + secp256r1Mod +}; + +#endif +#if (SECP384R1_SUPPORT == ENABLED) + +/** + * @brief secp384r1 elliptic curve + **/ + +const EcCurveInfo secp384r1Curve = +{ + //Curve name + "secp384r1", + //Object identifier + SECP384R1_OID, + sizeof(SECP384R1_OID), + //Curve type + EC_CURVE_TYPE_SECP_R1, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}, + 48, + //Curve parameter a + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC}, + 48, + //Curve parameter b + {0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B, 0xE3, 0xF8, 0x2D, 0x19, + 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12, 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, + 0xC6, 0x56, 0x39, 0x8D, 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF}, + 48, + //x-coordinate of the base point G + {0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E, 0xF3, 0x20, 0xAD, 0x74, + 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98, 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, + 0x55, 0x02, 0xF2, 0x5D, 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7}, + 48, + //y-coordinate of the base point G + {0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF, 0x92, 0x92, 0xDC, 0x29, + 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C, 0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, + 0x0A, 0x60, 0xB1, 0xCE, 0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F}, + 48, + //Base point order q + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, + 0x58, 0x1A, 0x0D, 0xB2, 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73}, + 48, + //Cofactor + 1, + //Fast modular reduction + secp384r1Mod +}; + +#endif +#if (SECP521R1_SUPPORT == ENABLED) + +/** + * @brief secp521r1 elliptic curve + **/ + +const EcCurveInfo secp521r1Curve = +{ + //Curve name + "secp521r1", + //Object identifier + SECP521R1_OID, + sizeof(SECP521R1_OID), + //Curve type + EC_CURVE_TYPE_SECP_R1, + //Prime modulus p + {0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF}, + 66, + //Curve parameter a + {0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFC}, + 66, + //Curve parameter b + {0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A, 0x21, 0xA0, 0xB6, 0x85, + 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3, 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, + 0x09, 0xE1, 0x56, 0x19, 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1, + 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45, 0x1F, 0xD4, 0x6B, 0x50, + 0x3F, 0x00}, + 66, + //x-coordinate of the base point G + {0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E, 0xCB, 0x66, 0x23, 0x95, + 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F, 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, + 0x3D, 0xBA, 0xA1, 0x4B, 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF, + 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E, 0x7E, 0x31, 0xC2, 0xE5, + 0xBD, 0x66}, + 66, + //y-coordinate of the base point G + {0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A, 0x5F, 0xB4, 0x2C, 0x7D, + 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B, 0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, + 0x66, 0x2C, 0x97, 0xEE, 0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD, + 0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE, 0x94, 0x76, 0x9F, 0xD1, + 0x66, 0x50}, + 66, + //Base point order q + {0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFA, 0x51, 0x86, 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09, + 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F, 0xB7, 0x1E, 0x91, 0x38, + 0x64, 0x09}, + 66, + //Cofactor + 1, + //Fast modular reduction + secp521r1Mod +}; + +#endif +#if (BRAINPOOLP160R1_SUPPORT == ENABLED) + +/** + * @brief brainpoolP160r1 elliptic curve + **/ + +const EcCurveInfo brainpoolP160r1Curve = +{ + //Curve name + "brainpoolP160r1", + //Object identifier + BRAINPOOLP160R1_OID, + sizeof(BRAINPOOLP160R1_OID), + //Curve type + EC_CURVE_TYPE_BRAINPOOLP_R1, + //Prime modulus p + {0xE9, 0x5E, 0x4A, 0x5F, 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0xC7, 0xAD, 0x95, 0xB3, 0xD8, 0x13, + 0x95, 0x15, 0x62, 0x0F}, + 20, + //Curve parameter a + {0x34, 0x0E, 0x7B, 0xE2, 0xA2, 0x80, 0xEB, 0x74, 0xE2, 0xBE, 0x61, 0xBA, 0xDA, 0x74, 0x5D, 0x97, + 0xE8, 0xF7, 0xC3, 0x00}, + 20, + //Curve parameter b + {0x1E, 0x58, 0x9A, 0x85, 0x95, 0x42, 0x34, 0x12, 0x13, 0x4F, 0xAA, 0x2D, 0xBD, 0xEC, 0x95, 0xC8, + 0xD8, 0x67, 0x5E, 0x58}, + 20, + //x-coordinate of the base point G + {0xBE, 0xD5, 0xAF, 0x16, 0xEA, 0x3F, 0x6A, 0x4F, 0x62, 0x93, 0x8C, 0x46, 0x31, 0xEB, 0x5A, 0xF7, + 0xBD, 0xBC, 0xDB, 0xC3}, + 20, + //y-coordinate of the base point G + {0x16, 0x67, 0xCB, 0x47, 0x7A, 0x1A, 0x8E, 0xC3, 0x38, 0xF9, 0x47, 0x41, 0x66, 0x9C, 0x97, 0x63, + 0x16, 0xDA, 0x63, 0x21}, + 20, + //Base point order q + {0xE9, 0x5E, 0x4A, 0x5F, 0x73, 0x70, 0x59, 0xDC, 0x60, 0xDF, 0x59, 0x91, 0xD4, 0x50, 0x29, 0x40, + 0x9E, 0x60, 0xFC, 0x09}, + 20, + //Cofactor + 1, + //Fast modular reduction + NULL +}; + +#endif +#if (BRAINPOOLP192R1_SUPPORT == ENABLED) + +/** + * @brief brainpoolP192r1 elliptic curve + **/ + +const EcCurveInfo brainpoolP192r1Curve = +{ + //Curve name + "brainpoolP192r1", + //Object identifier + BRAINPOOLP192R1_OID, + sizeof(BRAINPOOLP192R1_OID), + //Curve type + EC_CURVE_TYPE_BRAINPOOLP_R1, + //Prime modulus p + {0xC3, 0x02, 0xF4, 0x1D, 0x93, 0x2A, 0x36, 0xCD, 0xA7, 0xA3, 0x46, 0x30, 0x93, 0xD1, 0x8D, 0xB7, + 0x8F, 0xCE, 0x47, 0x6D, 0xE1, 0xA8, 0x62, 0x97}, + 24, + //Curve parameter a + {0x6A, 0x91, 0x17, 0x40, 0x76, 0xB1, 0xE0, 0xE1, 0x9C, 0x39, 0xC0, 0x31, 0xFE, 0x86, 0x85, 0xC1, + 0xCA, 0xE0, 0x40, 0xE5, 0xC6, 0x9A, 0x28, 0xEF}, + 24, + //Curve parameter b + {0x46, 0x9A, 0x28, 0xEF, 0x7C, 0x28, 0xCC, 0xA3, 0xDC, 0x72, 0x1D, 0x04, 0x4F, 0x44, 0x96, 0xBC, + 0xCA, 0x7E, 0xF4, 0x14, 0x6F, 0xBF, 0x25, 0xC9}, + 24, + //x-coordinate of the base point G + {0xC0, 0xA0, 0x64, 0x7E, 0xAA, 0xB6, 0xA4, 0x87, 0x53, 0xB0, 0x33, 0xC5, 0x6C, 0xB0, 0xF0, 0x90, + 0x0A, 0x2F, 0x5C, 0x48, 0x53, 0x37, 0x5F, 0xD6}, + 24, + //y-coordinate of the base point G + {0x14, 0xB6, 0x90, 0x86, 0x6A, 0xBD, 0x5B, 0xB8, 0x8B, 0x5F, 0x48, 0x28, 0xC1, 0x49, 0x00, 0x02, + 0xE6, 0x77, 0x3F, 0xA2, 0xFA, 0x29, 0x9B, 0x8F}, + 24, + //Base point order q + {0xC3, 0x02, 0xF4, 0x1D, 0x93, 0x2A, 0x36, 0xCD, 0xA7, 0xA3, 0x46, 0x2F, 0x9E, 0x9E, 0x91, 0x6B, + 0x5B, 0xE8, 0xF1, 0x02, 0x9A, 0xC4, 0xAC, 0xC1}, + 24, + //Cofactor + 1, + //Fast modular reduction + NULL +}; + +#endif +#if (BRAINPOOLP224R1_SUPPORT == ENABLED) + +/** + * @brief brainpoolP224r1 elliptic curve + **/ + +const EcCurveInfo brainpoolP224r1Curve = +{ + //Curve name + "brainpoolP224r1", + //Object identifier + BRAINPOOLP224R1_OID, + sizeof(BRAINPOOLP224R1_OID), + //Curve type + EC_CURVE_TYPE_BRAINPOOLP_R1, + //Prime modulus p + {0xD7, 0xC1, 0x34, 0xAA, 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25, 0x75, 0xD1, 0xD7, 0x87, + 0xB0, 0x9F, 0x07, 0x57, 0x97, 0xDA, 0x89, 0xF5, 0x7E, 0xC8, 0xC0, 0xFF}, + 28, + //Curve parameter a + {0x68, 0xA5, 0xE6, 0x2C, 0xA9, 0xCE, 0x6C, 0x1C, 0x29, 0x98, 0x03, 0xA6, 0xC1, 0x53, 0x0B, 0x51, + 0x4E, 0x18, 0x2A, 0xD8, 0xB0, 0x04, 0x2A, 0x59, 0xCA, 0xD2, 0x9F, 0x43}, + 28, + //Curve parameter b + {0x25, 0x80, 0xF6, 0x3C, 0xCF, 0xE4, 0x41, 0x38, 0x87, 0x07, 0x13, 0xB1, 0xA9, 0x23, 0x69, 0xE3, + 0x3E, 0x21, 0x35, 0xD2, 0x66, 0xDB, 0xB3, 0x72, 0x38, 0x6C, 0x40, 0x0B}, + 28, + //x-coordinate of the base point G + {0x0D, 0x90, 0x29, 0xAD, 0x2C, 0x7E, 0x5C, 0xF4, 0x34, 0x08, 0x23, 0xB2, 0xA8, 0x7D, 0xC6, 0x8C, + 0x9E, 0x4C, 0xE3, 0x17, 0x4C, 0x1E, 0x6E, 0xFD, 0xEE, 0x12, 0xC0, 0x7D}, + 28, + //y-coordinate of the base point G + {0x58, 0xAA, 0x56, 0xF7, 0x72, 0xC0, 0x72, 0x6F, 0x24, 0xC6, 0xB8, 0x9E, 0x4E, 0xCD, 0xAC, 0x24, + 0x35, 0x4B, 0x9E, 0x99, 0xCA, 0xA3, 0xF6, 0xD3, 0x76, 0x14, 0x02, 0xCD}, + 28, + //Base point order q + {0xD7, 0xC1, 0x34, 0xAA, 0x26, 0x43, 0x66, 0x86, 0x2A, 0x18, 0x30, 0x25, 0x75, 0xD0, 0xFB, 0x98, + 0xD1, 0x16, 0xBC, 0x4B, 0x6D, 0xDE, 0xBC, 0xA3, 0xA5, 0xA7, 0x93, 0x9F}, + 28, + //Cofactor + 1, + //Fast modular reduction + NULL +}; + +#endif +#if (BRAINPOOLP256R1_SUPPORT == ENABLED) + +/** + * @brief brainpoolP256r1 elliptic curve + **/ + +const EcCurveInfo brainpoolP256r1Curve = +{ + //Curve name + "brainpoolP256r1", + //Object identifier + BRAINPOOLP256R1_OID, + sizeof(BRAINPOOLP256R1_OID), + //Curve type + EC_CURVE_TYPE_BRAINPOOLP_R1, + //Prime modulus p + {0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x72, + 0x6E, 0x3B, 0xF6, 0x23, 0xD5, 0x26, 0x20, 0x28, 0x20, 0x13, 0x48, 0x1D, 0x1F, 0x6E, 0x53, 0x77}, + 32, + //Curve parameter a + {0x7D, 0x5A, 0x09, 0x75, 0xFC, 0x2C, 0x30, 0x57, 0xEE, 0xF6, 0x75, 0x30, 0x41, 0x7A, 0xFF, 0xE7, + 0xFB, 0x80, 0x55, 0xC1, 0x26, 0xDC, 0x5C, 0x6C, 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9}, + 32, + //Curve parameter b + {0x26, 0xDC, 0x5C, 0x6C, 0xE9, 0x4A, 0x4B, 0x44, 0xF3, 0x30, 0xB5, 0xD9, 0xBB, 0xD7, 0x7C, 0xBF, + 0x95, 0x84, 0x16, 0x29, 0x5C, 0xF7, 0xE1, 0xCE, 0x6B, 0xCC, 0xDC, 0x18, 0xFF, 0x8C, 0x07, 0xB6}, + 32, + //x-coordinate of the base point G + {0x8B, 0xD2, 0xAE, 0xB9, 0xCB, 0x7E, 0x57, 0xCB, 0x2C, 0x4B, 0x48, 0x2F, 0xFC, 0x81, 0xB7, 0xAF, + 0xB9, 0xDE, 0x27, 0xE1, 0xE3, 0xBD, 0x23, 0xC2, 0x3A, 0x44, 0x53, 0xBD, 0x9A, 0xCE, 0x32, 0x62}, + 32, + //y-coordinate of the base point G + {0x54, 0x7E, 0xF8, 0x35, 0xC3, 0xDA, 0xC4, 0xFD, 0x97, 0xF8, 0x46, 0x1A, 0x14, 0x61, 0x1D, 0xC9, + 0xC2, 0x77, 0x45, 0x13, 0x2D, 0xED, 0x8E, 0x54, 0x5C, 0x1D, 0x54, 0xC7, 0x2F, 0x04, 0x69, 0x97}, + 32, + //Base point order q + {0xA9, 0xFB, 0x57, 0xDB, 0xA1, 0xEE, 0xA9, 0xBC, 0x3E, 0x66, 0x0A, 0x90, 0x9D, 0x83, 0x8D, 0x71, + 0x8C, 0x39, 0x7A, 0xA3, 0xB5, 0x61, 0xA6, 0xF7, 0x90, 0x1E, 0x0E, 0x82, 0x97, 0x48, 0x56, 0xA7}, + 32, + //Cofactor + 1, + //Fast modular reduction + NULL +}; + +#endif +#if (BRAINPOOLP320R1_SUPPORT == ENABLED) + +/** + * @brief brainpoolP320r1 elliptic curve + **/ + +const EcCurveInfo brainpoolP320r1Curve = +{ + //Curve name + "brainpoolP320r1", + //Object identifier + BRAINPOOLP320R1_OID, + sizeof(BRAINPOOLP320R1_OID), + //Curve type + EC_CURVE_TYPE_BRAINPOOLP_R1, + //Prime modulus p + {0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E, 0xD2, 0x01, 0xE0, 0x65, + 0xF9, 0x8F, 0xCF, 0xA6, 0xF6, 0xF4, 0x0D, 0xEF, 0x4F, 0x92, 0xB9, 0xEC, 0x78, 0x93, 0xEC, 0x28, + 0xFC, 0xD4, 0x12, 0xB1, 0xF1, 0xB3, 0x2E, 0x27}, + 40, + //Curve parameter a + {0x3E, 0xE3, 0x0B, 0x56, 0x8F, 0xBA, 0xB0, 0xF8, 0x83, 0xCC, 0xEB, 0xD4, 0x6D, 0x3F, 0x3B, 0xB8, + 0xA2, 0xA7, 0x35, 0x13, 0xF5, 0xEB, 0x79, 0xDA, 0x66, 0x19, 0x0E, 0xB0, 0x85, 0xFF, 0xA9, 0xF4, + 0x92, 0xF3, 0x75, 0xA9, 0x7D, 0x86, 0x0E, 0xB4}, + 40, + //Curve parameter b + {0x52, 0x08, 0x83, 0x94, 0x9D, 0xFD, 0xBC, 0x42, 0xD3, 0xAD, 0x19, 0x86, 0x40, 0x68, 0x8A, 0x6F, + 0xE1, 0x3F, 0x41, 0x34, 0x95, 0x54, 0xB4, 0x9A, 0xCC, 0x31, 0xDC, 0xCD, 0x88, 0x45, 0x39, 0x81, + 0x6F, 0x5E, 0xB4, 0xAC, 0x8F, 0xB1, 0xF1, 0xA6}, + 40, + //x-coordinate of the base point G + {0x43, 0xBD, 0x7E, 0x9A, 0xFB, 0x53, 0xD8, 0xB8, 0x52, 0x89, 0xBC, 0xC4, 0x8E, 0xE5, 0xBF, 0xE6, + 0xF2, 0x01, 0x37, 0xD1, 0x0A, 0x08, 0x7E, 0xB6, 0xE7, 0x87, 0x1E, 0x2A, 0x10, 0xA5, 0x99, 0xC7, + 0x10, 0xAF, 0x8D, 0x0D, 0x39, 0xE2, 0x06, 0x11}, + 40, + //y-coordinate of the base point G + {0x14, 0xFD, 0xD0, 0x55, 0x45, 0xEC, 0x1C, 0xC8, 0xAB, 0x40, 0x93, 0x24, 0x7F, 0x77, 0x27, 0x5E, + 0x07, 0x43, 0xFF, 0xED, 0x11, 0x71, 0x82, 0xEA, 0xA9, 0xC7, 0x78, 0x77, 0xAA, 0xAC, 0x6A, 0xC7, + 0xD3, 0x52, 0x45, 0xD1, 0x69, 0x2E, 0x8E, 0xE1}, + 40, + //Base point order q + {0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E, 0xD2, 0x01, 0xE0, 0x65, + 0xF9, 0x8F, 0xCF, 0xA5, 0xB6, 0x8F, 0x12, 0xA3, 0x2D, 0x48, 0x2E, 0xC7, 0xEE, 0x86, 0x58, 0xE9, + 0x86, 0x91, 0x55, 0x5B, 0x44, 0xC5, 0x93, 0x11}, + 40, + //Cofactor + 1, + //Fast modular reduction + NULL +}; + +#endif +#if (BRAINPOOLP384R1_SUPPORT == ENABLED) + +/** + * @brief brainpoolP384r1 elliptic curve + **/ + +const EcCurveInfo brainpoolP384r1Curve = +{ + //Curve name + "brainpoolP384r1", + //Object identifier + BRAINPOOLP384R1_OID, + sizeof(BRAINPOOLP384R1_OID), + //Curve type + EC_CURVE_TYPE_BRAINPOOLP_R1, + //Prime modulus p + {0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E, 0x50, 0xE6, 0x41, 0xDF, + 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB4, 0x12, 0xB1, 0xDA, 0x19, 0x7F, 0xB7, 0x11, 0x23, + 0xAC, 0xD3, 0xA7, 0x29, 0x90, 0x1D, 0x1A, 0x71, 0x87, 0x47, 0x00, 0x13, 0x31, 0x07, 0xEC, 0x53}, + 48, + //Curve parameter a + {0x7B, 0xC3, 0x82, 0xC6, 0x3D, 0x8C, 0x15, 0x0C, 0x3C, 0x72, 0x08, 0x0A, 0xCE, 0x05, 0xAF, 0xA0, + 0xC2, 0xBE, 0xA2, 0x8E, 0x4F, 0xB2, 0x27, 0x87, 0x13, 0x91, 0x65, 0xEF, 0xBA, 0x91, 0xF9, 0x0F, + 0x8A, 0xA5, 0x81, 0x4A, 0x50, 0x3A, 0xD4, 0xEB, 0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26}, + 48, + //Curve parameter b + {0x04, 0xA8, 0xC7, 0xDD, 0x22, 0xCE, 0x28, 0x26, 0x8B, 0x39, 0xB5, 0x54, 0x16, 0xF0, 0x44, 0x7C, + 0x2F, 0xB7, 0x7D, 0xE1, 0x07, 0xDC, 0xD2, 0xA6, 0x2E, 0x88, 0x0E, 0xA5, 0x3E, 0xEB, 0x62, 0xD5, + 0x7C, 0xB4, 0x39, 0x02, 0x95, 0xDB, 0xC9, 0x94, 0x3A, 0xB7, 0x86, 0x96, 0xFA, 0x50, 0x4C, 0x11}, + 48, + //x-coordinate of the base point G + {0x1D, 0x1C, 0x64, 0xF0, 0x68, 0xCF, 0x45, 0xFF, 0xA2, 0xA6, 0x3A, 0x81, 0xB7, 0xC1, 0x3F, 0x6B, + 0x88, 0x47, 0xA3, 0xE7, 0x7E, 0xF1, 0x4F, 0xE3, 0xDB, 0x7F, 0xCA, 0xFE, 0x0C, 0xBD, 0x10, 0xE8, + 0xE8, 0x26, 0xE0, 0x34, 0x36, 0xD6, 0x46, 0xAA, 0xEF, 0x87, 0xB2, 0xE2, 0x47, 0xD4, 0xAF, 0x1E}, + 48, + //y-coordinate of the base point G + {0x8A, 0xBE, 0x1D, 0x75, 0x20, 0xF9, 0xC2, 0xA4, 0x5C, 0xB1, 0xEB, 0x8E, 0x95, 0xCF, 0xD5, 0x52, + 0x62, 0xB7, 0x0B, 0x29, 0xFE, 0xEC, 0x58, 0x64, 0xE1, 0x9C, 0x05, 0x4F, 0xF9, 0x91, 0x29, 0x28, + 0x0E, 0x46, 0x46, 0x21, 0x77, 0x91, 0x81, 0x11, 0x42, 0x82, 0x03, 0x41, 0x26, 0x3C, 0x53, 0x15}, + 48, + //Base point order q + {0x8C, 0xB9, 0x1E, 0x82, 0xA3, 0x38, 0x6D, 0x28, 0x0F, 0x5D, 0x6F, 0x7E, 0x50, 0xE6, 0x41, 0xDF, + 0x15, 0x2F, 0x71, 0x09, 0xED, 0x54, 0x56, 0xB3, 0x1F, 0x16, 0x6E, 0x6C, 0xAC, 0x04, 0x25, 0xA7, + 0xCF, 0x3A, 0xB6, 0xAF, 0x6B, 0x7F, 0xC3, 0x10, 0x3B, 0x88, 0x32, 0x02, 0xE9, 0x04, 0x65, 0x65}, + 48, + //Cofactor + 1, + //Fast modular reduction + NULL +}; + +#endif +#if (BRAINPOOLP512R1_SUPPORT == ENABLED) + +/** + * @brief brainpoolP512r1 elliptic curve + **/ + +const EcCurveInfo brainpoolP512r1Curve = +{ + //Curve name + "brainpoolP512r1", + //Object identifier + BRAINPOOLP512R1_OID, + sizeof(BRAINPOOLP512R1_OID), + //Curve type + EC_CURVE_TYPE_BRAINPOOLP_R1, + //Prime modulus p + {0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE, 0x33, 0xC9, 0xFC, 0x07, + 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E, 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x71, + 0x7D, 0x4D, 0x9B, 0x00, 0x9B, 0xC6, 0x68, 0x42, 0xAE, 0xCD, 0xA1, 0x2A, 0xE6, 0xA3, 0x80, 0xE6, + 0x28, 0x81, 0xFF, 0x2F, 0x2D, 0x82, 0xC6, 0x85, 0x28, 0xAA, 0x60, 0x56, 0x58, 0x3A, 0x48, 0xF3}, + 64, + //Curve parameter a + {0x78, 0x30, 0xA3, 0x31, 0x8B, 0x60, 0x3B, 0x89, 0xE2, 0x32, 0x71, 0x45, 0xAC, 0x23, 0x4C, 0xC5, + 0x94, 0xCB, 0xDD, 0x8D, 0x3D, 0xF9, 0x16, 0x10, 0xA8, 0x34, 0x41, 0xCA, 0xEA, 0x98, 0x63, 0xBC, + 0x2D, 0xED, 0x5D, 0x5A, 0xA8, 0x25, 0x3A, 0xA1, 0x0A, 0x2E, 0xF1, 0xC9, 0x8B, 0x9A, 0xC8, 0xB5, + 0x7F, 0x11, 0x17, 0xA7, 0x2B, 0xF2, 0xC7, 0xB9, 0xE7, 0xC1, 0xAC, 0x4D, 0x77, 0xFC, 0x94, 0xCA}, + 64, + //Curve parameter b + {0x3D, 0xF9, 0x16, 0x10, 0xA8, 0x34, 0x41, 0xCA, 0xEA, 0x98, 0x63, 0xBC, 0x2D, 0xED, 0x5D, 0x5A, + 0xA8, 0x25, 0x3A, 0xA1, 0x0A, 0x2E, 0xF1, 0xC9, 0x8B, 0x9A, 0xC8, 0xB5, 0x7F, 0x11, 0x17, 0xA7, + 0x2B, 0xF2, 0xC7, 0xB9, 0xE7, 0xC1, 0xAC, 0x4D, 0x77, 0xFC, 0x94, 0xCA, 0xDC, 0x08, 0x3E, 0x67, + 0x98, 0x40, 0x50, 0xB7, 0x5E, 0xBA, 0xE5, 0xDD, 0x28, 0x09, 0xBD, 0x63, 0x80, 0x16, 0xF7, 0x23}, + 64, + //x-coordinate of the base point G + {0x81, 0xAE, 0xE4, 0xBD, 0xD8, 0x2E, 0xD9, 0x64, 0x5A, 0x21, 0x32, 0x2E, 0x9C, 0x4C, 0x6A, 0x93, + 0x85, 0xED, 0x9F, 0x70, 0xB5, 0xD9, 0x16, 0xC1, 0xB4, 0x3B, 0x62, 0xEE, 0xF4, 0xD0, 0x09, 0x8E, + 0xFF, 0x3B, 0x1F, 0x78, 0xE2, 0xD0, 0xD4, 0x8D, 0x50, 0xD1, 0x68, 0x7B, 0x93, 0xB9, 0x7D, 0x5F, + 0x7C, 0x6D, 0x50, 0x47, 0x40, 0x6A, 0x5E, 0x68, 0x8B, 0x35, 0x22, 0x09, 0xBC, 0xB9, 0xF8, 0x22}, + 64, + //y-coordinate of the base point G + {0x7D, 0xDE, 0x38, 0x5D, 0x56, 0x63, 0x32, 0xEC, 0xC0, 0xEA, 0xBF, 0xA9, 0xCF, 0x78, 0x22, 0xFD, + 0xF2, 0x09, 0xF7, 0x00, 0x24, 0xA5, 0x7B, 0x1A, 0xA0, 0x00, 0xC5, 0x5B, 0x88, 0x1F, 0x81, 0x11, + 0xB2, 0xDC, 0xDE, 0x49, 0x4A, 0x5F, 0x48, 0x5E, 0x5B, 0xCA, 0x4B, 0xD8, 0x8A, 0x27, 0x63, 0xAE, + 0xD1, 0xCA, 0x2B, 0x2F, 0xA8, 0xF0, 0x54, 0x06, 0x78, 0xCD, 0x1E, 0x0F, 0x3A, 0xD8, 0x08, 0x92}, + 64, + //Base point order q + {0xAA, 0xDD, 0x9D, 0xB8, 0xDB, 0xE9, 0xC4, 0x8B, 0x3F, 0xD4, 0xE6, 0xAE, 0x33, 0xC9, 0xFC, 0x07, + 0xCB, 0x30, 0x8D, 0xB3, 0xB3, 0xC9, 0xD2, 0x0E, 0xD6, 0x63, 0x9C, 0xCA, 0x70, 0x33, 0x08, 0x70, + 0x55, 0x3E, 0x5C, 0x41, 0x4C, 0xA9, 0x26, 0x19, 0x41, 0x86, 0x61, 0x19, 0x7F, 0xAC, 0x10, 0x47, + 0x1D, 0xB1, 0xD3, 0x81, 0x08, 0x5D, 0xDA, 0xDD, 0xB5, 0x87, 0x96, 0x82, 0x9C, 0xA9, 0x00, 0x69}, + 64, + //Cofactor + 1, + //Fast modular reduction + NULL +}; + +#endif +#if (SM2_SUPPORT == ENABLED) + +/** + * @brief SM2 elliptic curve + **/ + +const EcCurveInfo sm2Curve = +{ + //Curve name + "curveSM2", + //Object identifier + SM2_OID, + sizeof(SM2_OID), + //Curve type + EC_CURVE_TYPE_SECP_R1, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + 32, + //Curve parameter a + {0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC}, + 32, + //Curve parameter b + {0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34, 0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7, + 0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92, 0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93}, + 32, + //x-coordinate of the base point G + {0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19, 0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94, + 0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1, 0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7}, + 32, + //y-coordinate of the base point G + {0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C, 0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53, + 0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40, 0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0}, + 32, + //Base point order q + {0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x72, 0x03, 0xDF, 0x6B, 0x21, 0xC6, 0x05, 0x2B, 0x53, 0xBB, 0xF4, 0x09, 0x39, 0xD5, 0x41, 0x23}, + 32, + //Cofactor + 1, + //Fast modular reduction + sm2Mod +}; + +#endif +#if (X25519_SUPPORT == ENABLED) + +/** + * @brief Curve25519 elliptic curve + **/ + +const EcCurveInfo x25519Curve = +{ + //Curve name + "curve25519", + //Object identifier + X25519_OID, + sizeof(X25519_OID), + //Curve type + EC_CURVE_TYPE_X25519, + //Prime modulus p + {0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED}, + 32, + //Curve parameter a + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x6D, 0x06}, + 32, + //Curve parameter b + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + 32, + //u-coordinate of the base point G + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09}, + 32, + //v-coordinate of the base point G + {0x20, 0xAE, 0x19, 0xA1, 0xB8, 0xA0, 0x86, 0xB4, 0xE0, 0x1E, 0xDD, 0x2C, 0x77, 0x48, 0xD1, 0x4C, + 0x92, 0x3D, 0x4D, 0x7E, 0x6D, 0x7C, 0x61, 0xB2, 0x29, 0xE9, 0xC5, 0xA2, 0x7E, 0xCE, 0xD3, 0xD9}, + 32, + //Base point order q + {0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6, 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED}, + 32, + //Cofactor + 8, + //Fast modular reduction + NULL +}; + +#endif +#if (X448_SUPPORT == ENABLED) + +/** + * @brief Curve448 elliptic curve + **/ + +const EcCurveInfo x448Curve = +{ + //Curve name + "curve448", + //Object identifier + X448_OID, + sizeof(X448_OID), + //Curve type + EC_CURVE_TYPE_X448, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + 56, + //Curve parameter a + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x62, 0xA6}, + 56, + //Curve parameter b + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + 56, + //u-coordinate of the base point G + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + 56, + //v-coordinate of the base point G + {0x7D, 0x23, 0x5D, 0x12, 0x95, 0xF5, 0xB1, 0xF6, 0x6C, 0x98, 0xAB, 0x6E, 0x58, 0x32, 0x6F, 0xCE, + 0xCB, 0xAE, 0x5D, 0x34, 0xF5, 0x55, 0x45, 0xD0, 0x60, 0xF7, 0x5D, 0xC2, 0x8D, 0xF3, 0xF6, 0xED, + 0xB8, 0x02, 0x7E, 0x23, 0x46, 0x43, 0x0D, 0x21, 0x13, 0x12, 0xC4, 0xB1, 0x50, 0x67, 0x7A, 0xF7, + 0x6F, 0xD7, 0x22, 0x3D, 0x45, 0x7B, 0x5B, 0x1A}, + 56, + //Base point order q + {0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0xCA, 0x23, 0xE9, + 0xC4, 0x4E, 0xDB, 0x49, 0xAE, 0xD6, 0x36, 0x90, 0x21, 0x6C, 0xC2, 0x72, 0x8D, 0xC5, 0x8F, 0x55, + 0x23, 0x78, 0xC2, 0x92, 0xAB, 0x58, 0x44, 0xF3}, + 56, + //Cofactor + 4, + //Fast modular reduction + NULL +}; + +#endif +#if (ED25519_SUPPORT == ENABLED) + +/** + * @brief Ed25519 elliptic curve + **/ + +const EcCurveInfo ed25519Curve = +{ + //Curve name + "Ed25519", + //Object identifier + ED25519_OID, + sizeof(ED25519_OID), + //Curve type + EC_CURVE_TYPE_ED25519, + //Prime modulus p + {0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED}, + 32, + //Curve parameter a + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x6D, 0x06}, + 32, + //Curve parameter b + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + 32, + //x-coordinate of the base point G + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09}, + 32, + //y-coordinate of the base point G + {0x20, 0xAE, 0x19, 0xA1, 0xB8, 0xA0, 0x86, 0xB4, 0xE0, 0x1E, 0xDD, 0x2C, 0x77, 0x48, 0xD1, 0x4C, + 0x92, 0x3D, 0x4D, 0x7E, 0x6D, 0x7C, 0x61, 0xB2, 0x29, 0xE9, 0xC5, 0xA2, 0x7E, 0xCE, 0xD3, 0xD9}, + 32, + //Base point order q + {0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6, 0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED}, + 32, + //Cofactor + 8, + //Fast modular reduction + NULL +}; + +#endif +#if (ED448_SUPPORT == ENABLED) + +/** + * @brief Ed448 elliptic curve + **/ + +const EcCurveInfo ed448Curve = +{ + //Curve name + "Ed448", + //Object identifier + ED448_OID, + sizeof(ED448_OID), + //Curve type + EC_CURVE_TYPE_ED448, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + 56, + //Curve parameter a + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x62, 0xA6}, + 56, + //Curve parameter b + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + 56, + //x-coordinate of the base point G + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05}, + 56, + //y-coordinate of the base point G + {0x7D, 0x23, 0x5D, 0x12, 0x95, 0xF5, 0xB1, 0xF6, 0x6C, 0x98, 0xAB, 0x6E, 0x58, 0x32, 0x6F, 0xCE, + 0xCB, 0xAE, 0x5D, 0x34, 0xF5, 0x55, 0x45, 0xD0, 0x60, 0xF7, 0x5D, 0xC2, 0x8D, 0xF3, 0xF6, 0xED, + 0xB8, 0x02, 0x7E, 0x23, 0x46, 0x43, 0x0D, 0x21, 0x13, 0x12, 0xC4, 0xB1, 0x50, 0x67, 0x7A, 0xF7, + 0x6F, 0xD7, 0x22, 0x3D, 0x45, 0x7B, 0x5B, 0x1A}, + 56, + //Base point order q + {0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0xCA, 0x23, 0xE9, + 0xC4, 0x4E, 0xDB, 0x49, 0xAE, 0xD6, 0x36, 0x90, 0x21, 0x6C, 0xC2, 0x72, 0x8D, 0xC5, 0x8F, 0x55, + 0x23, 0x78, 0xC2, 0x92, 0xAB, 0x58, 0x44, 0xF3}, + 56, + //Cofactor + 4, + //Fast modular reduction + NULL +}; + +#endif +#if (TC26SIGN512A_SUPPORT == ENABLED) + +/** + * @brief tc26Sign512a elliptic curve + * tc26Sign512a curves first recommended in 2013 and then standardized in + * R 50.1.114-2016 and RFC 7836 for use with GOST R 34.10-2012 (as TC26 + * 512-bit ParamSetA). + **/ + +const EcCurveInfo tc26Sign512aCurve = +{ + //Curve name + "tc26Sign512a", + //Object identifier + TC26SIGN512A_OID, + sizeof(TC26SIGN512A_OID), + //Curve type + EC_CURVE_TYPE_TC26SIGN512A, + //Prime modulus p + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xC7}, + 64, + //Curve parameter a + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xC4}, + 64, + //Curve parameter b + {0xE8, 0xC2, 0x50, 0x5D, 0xED, 0xFC, 0x86, 0xDD, 0xC1, 0xBD, 0x0B, 0x2B, 0x66, 0x67, 0xF1, 0xDA, + 0x34, 0xB8, 0x25, 0x74, 0x76, 0x1C, 0xB0, 0xE8, 0x79, 0xBD, 0x08, 0x1C, 0xFD, 0x0B, 0x62, 0x65, + 0xEE, 0x3C, 0xB0, 0x90, 0xF3, 0x0D, 0x27, 0x61, 0x4C, 0xB4, 0x57, 0x40, 0x10, 0xDA, 0x90, 0xDD, + 0x86, 0x2E, 0xF9, 0xD4, 0xEB, 0xEE, 0x47, 0x61, 0x50, 0x31, 0x90, 0x78, 0x5A, 0x71, 0xC7, 0x60}, + 64, + //x-coordinate of the base point G + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}, + 64, + //y-coordinate of the base point G + {0x75, 0x03, 0xCF, 0xE8, 0x7A, 0x83, 0x6A, 0xE3, 0xA6, 0x1B, 0x88, 0x16, 0xE2, 0x54, 0x50, 0xE6, 0xCE, 0x5E, 0x1C, 0x93, 0xAC, 0xF1, 0xAB, 0xC1, 0x77, 0x80, 0x64, 0xFD, 0xCB, 0xEF, 0xA9, 0x21, 0xDF, 0x16, 0x26, 0xBE, 0x4F, 0xD0, 0x36, 0xE9, 0x3D, 0x75, 0xE6, 0xA5, 0x0E, 0x3A, 0x41, 0xE9, 0x80, 0x28, 0xFE, 0x5F, 0xC2, 0x35, 0xF5, 0xB8, 0x89, 0xA5, 0x89, 0xCB, 0x52, 0x15, 0xF2, 0xA4}, 64, //Base point order q + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x27, 0xE6, 0x95, 0x32, 0xF4, 0x8D, 0x89, 0x11, 0x6F, 0xF2, 0x2B, 0x8D, 0x4E, 0x05, 0x60, 0x60, + 0x9B, 0x4B, 0x38, 0xAB, 0xFA, 0xD2, 0xB8, 0x5D, 0xCA, 0xCD, 0xB1, 0x41, 0x1F, 0x10, 0xB2, 0x75}, + 64, + //Cofactor + 1, + //Fast modular reduction + NULL +}; + +#endif +#if (TC26SIGN512B_SUPPORT == ENABLED) + +/** + * @brief tc26Sign512a elliptic curve + * tc26Sign512a curves first recommended in 2013 and then standardized in + * R 50.1.114-2016 and RFC 7836 for use with GOST R 34.10-2012 (as TC26 + * 512-bit ParamSetA). + **/ + +const EcCurveInfo tc26Sign512bCurve = +{ + //Curve name + "tc26Sign512b", + //Object identifier + TC26SIGN512B_OID, + sizeof(TC26SIGN512B_OID), + //Curve type + EC_CURVE_TYPE_TC26SIGN512B, + //Prime modulus p + {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6F}, + 64, + //Curve parameter a + {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C}, + 64, + //Curve parameter b + {0x68, 0x7D, 0x1B, 0x45, 0x9D, 0xC8, 0x41, 0x45, 0x7E, 0x3E, 0x06, 0xCF, 0x6F, 0x5E, 0x25, 0x17, + 0xB9, 0x7C, 0x7D, 0x61, 0x4A, 0xF1, 0x38, 0xBC, 0xBF, 0x85, 0xDC, 0x80, 0x6C, 0x4B, 0x28, 0x9F, + 0x3E, 0x96, 0x5D, 0x2D, 0xB1, 0x41, 0x6D, 0x21, 0x7F, 0x8B, 0x27, 0x6F, 0xAD, 0x1A, 0xB6, 0x9C, + 0x50, 0xF7, 0x8B, 0xEE, 0x1F, 0xA3, 0x10, 0x6E, 0xFB, 0x8C, 0xCB, 0xC7, 0xC5, 0x14, 0x01, 0x16}, + 64, + //x-coordinate of the base point G + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, + 64, + //y-coordinate of the base point G + {0x1A, 0x8F, 0x7E, 0xDA, 0x38, 0x9B, 0x09, 0x4C, 0x2C, 0x07, 0x1E, 0x36, 0x47, 0xA8, 0x94, 0x0F, + 0x3C, 0x12, 0x3B, 0x69, 0x75, 0x78, 0xC2, 0x13, 0xBE, 0x6D, 0xD9, 0xE6, 0xC8, 0xEC, 0x73, 0x35, + 0xDC, 0xB2, 0x28, 0xFD, 0x1E, 0xDF, 0x4A, 0x39, 0x15, 0x2C, 0xBC, 0xAA, 0xF8, 0xC0, 0x39, 0x88, + 0x28, 0x04, 0x10, 0x55, 0xF9, 0x4C, 0xEE, 0xEC, 0x7E, 0x21, 0x34, 0x07, 0x80, 0xFE, 0x41, 0xBD}, 64, //Base point order q + {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x49, 0xA1, 0xEC, 0x14, 0x25, 0x65, 0xA5, 0x45, 0xAC, 0xFD, 0xB7, 0x7B, 0xD9, 0xD4, 0x0C, 0xFA, + 0x8B, 0x99, 0x67, 0x12, 0x10, 0x1B, 0xEA, 0x0E, 0xC6, 0x34, 0x6C, 0x54, 0x37, 0x4F, 0x25, 0xBD}, + 64, + //Cofactor + 1, + //Fast modular reduction + NULL +}; + +#endif + +#if (SECP128R1_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (secp128r1 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t secp128r1Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi t; + + //Initialize multiple precision integers + mpiInit(&t); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 32 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 32 / MPI_INT_SIZE)); + + //Perform modular reduction + do + { + //Compute T = 0 | 0 | 0 | 0 | A7 | A6 | A5 | A4 + COPY_WORD32(&t, 0, a, 4, 4); + CLEAR_WORD32(&t, 4, 4); + + //Clear A7 | A6 | A5 | A4 + CLEAR_WORD32(a, 4, 4); + + //Compute A = A + T + (T << 97) + MPI_CHECK(mpiAdd(a, a, &t)); + MPI_CHECK(mpiShiftLeft(&t, 97)); + MPI_CHECK(mpiAdd(a, a, &t)); + + //Check for end condition + } while(mpiComp(a, p) > 0); + +end: + //Release multiple precision integers + mpiFree(&t); + + //Return status code + return error; +} + +#endif +#if (SECP128R2_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (secp128r2 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t secp128r2Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi t; + + //Initialize multiple precision integers + mpiInit(&t); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 32 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 32 / MPI_INT_SIZE)); + + //Perform modular reduction + do + { + //Compute T = 0 | 0 | 0 | 0 | A7 | A6 | A5 | A4 + COPY_WORD32(&t, 0, a, 4, 4); + CLEAR_WORD32(&t, 4, 4); + + //Clear A7 | A6 | A5 | A4 + CLEAR_WORD32(a, 4, 4); + + //Compute A = A + T + (T << 97) + MPI_CHECK(mpiAdd(a, a, &t)); + MPI_CHECK(mpiShiftLeft(&t, 97)); + MPI_CHECK(mpiAdd(a, a, &t)); + + //Check for end condition + } while(mpiComp(a, p) > 0); + +end: + //Release multiple precision integers + mpiFree(&t); + + //Return status code + return error; +} + +#endif +#if (SECP160K1_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (secp160k1 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t secp160k1Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi t; + + //Initialize multiple precision integers + mpiInit(&t); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 40 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 24 / MPI_INT_SIZE)); + + //Perform modular reduction + do + { + //Compute T = A9 | A8 | A7 | A6 | A5 | 0 + CLEAR_WORD32(&t, 0, 1); + COPY_WORD32(&t, 1, a, 5, 5); + + //Clear A9 | A8 | A7 | A6 | A5 + CLEAR_WORD32(a, 5, 5); + + //Compute A = A + T + MPI_CHECK(mpiAdd(a, a, &t)); + //Compute T = T >> 32 + MPI_CHECK(mpiShiftRight(&t, 32)); + //Compute A = A + (21389 * T) + MPI_CHECK(mpiMulInt(&t, &t, 21389)); + MPI_CHECK(mpiAdd(a, a, &t)); + + //Check for end condition + } while(mpiComp(a, p) > 0); + +end: + //Release multiple precision integers + mpiFree(&t); + + //Return status code + return error; +} + +#endif +#if (SECP160R1_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (secp160r1 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t secp160r1Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi t; + + //Initialize multiple precision integers + mpiInit(&t); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 40 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 24 / MPI_INT_SIZE)); + + //Perform modular reduction + do + { + //Compute T = 0 | A9 | A8 | A7 | A6 | A5 + COPY_WORD32(&t, 0, a, 5, 5); + CLEAR_WORD32(&t, 5, 1); + + //Clear A9 | A8 | A7 | A6 | A5 + CLEAR_WORD32(a, 5, 5); + + //Compute A = A + T + (T << 31) + MPI_CHECK(mpiAdd(a, a, &t)); + MPI_CHECK(mpiShiftLeft(&t, 31)); + MPI_CHECK(mpiAdd(a, a, &t)); + + //Check for end condition + } while(mpiComp(a, p) > 0); + +end: + //Release multiple precision integers + mpiFree(&t); + + //Return status code + return error; +} + +#endif +#if (SECP160R2_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (secp160r2 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t secp160r2Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi t; + + //Initialize multiple precision integers + mpiInit(&t); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 40 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 24 / MPI_INT_SIZE)); + + //Perform modular reduction + do + { + //Compute T = A9 | A8 | A7 | A6 | A5 | 0 + CLEAR_WORD32(&t, 0, 1); + COPY_WORD32(&t, 1, a, 5, 5); + + //Clear A9 | A8 | A7 | A6 | A5 + CLEAR_WORD32(a, 5, 5); + + //Compute A = A + T + MPI_CHECK(mpiAdd(a, a, &t)); + //Compute T = T >> 32 + MPI_CHECK(mpiShiftRight(&t, 32)); + //Compute A = A + (21389 * T) + MPI_CHECK(mpiMulInt(&t, &t, 21389)); + MPI_CHECK(mpiAdd(a, a, &t)); + + //Check for end condition + } while(mpiComp(a, p) > 0); + +end: + //Release multiple precision integers + mpiFree(&t); + + //Return status code + return error; +} + +#endif +#if (SECP192K1_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (secp192k1 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t secp192k1Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi t; + + //Initialize multiple precision integers + mpiInit(&t); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 48 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 28 / MPI_INT_SIZE)); + + //Perform modular reduction + do + { + //Compute T = A11 | A10 | A9 | A8 | A7 | A6 | 0 + CLEAR_WORD32(&t, 0, 1); + COPY_WORD32(&t, 1, a, 6, 6); + + //Clear A11 | A10 | A9 | A8 | A7 | A6 + CLEAR_WORD32(a, 6, 6); + + //Compute A = A + T + MPI_CHECK(mpiAdd(a, a, &t)); + //Compute T = T >> 32 + MPI_CHECK(mpiShiftRight(&t, 32)); + //Compute A = A + (4553 * T) + MPI_CHECK(mpiMulInt(&t, &t, 4553)); + MPI_CHECK(mpiAdd(a, a, &t)); + + //Check for end condition + } while(mpiComp(a, p) > 0); + +end: + //Release multiple precision integers + mpiFree(&t); + + //Return status code + return error; +} + +#endif +#if (SECP192R1_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (secp192r1 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t secp192r1Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi s; + Mpi t; + + //Initialize multiple precision integers + mpiInit(&s); + mpiInit(&t); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 48 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&s, 24 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 24 / MPI_INT_SIZE)); + + //Compute T = A5 | A4 | A3 | A2 | A1 | A0 + COPY_WORD32(&t, 0, a, 0, 6); + + //Compute S1 = 0 | 0 | A7 | A6 | A7 | A6 + COPY_WORD32(&s, 0, a, 6, 2); + COPY_WORD32(&s, 2, a, 6, 2); + CLEAR_WORD32(&s, 4, 2); + //Compute T = T + S1 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S2 = A9 | A8 | A9 | A8 | 0 | 0 + CLEAR_WORD32(&s, 0, 2); + COPY_WORD32(&s, 2, a, 8, 2); + COPY_WORD32(&s, 4, a, 8, 2); + //Compute T = T + S2 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S3 = A11 | A10 | A11 | A10 | A11 | A10 + COPY_WORD32(&s, 0, a, 10, 2); + COPY_WORD32(&s, 2, a, 10, 2); + COPY_WORD32(&s, 4, a, 10, 2); + //Compute T = T + S3 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute (T + S1 + S2 + S3) mod p + while(mpiComp(&t, p) >= 0) + { + MPI_CHECK(mpiSub(&t, &t, p)); + } + + //Save result + MPI_CHECK(mpiCopy(a, &t)); + +end: + //Release multiple precision integers + mpiFree(&s); + mpiFree(&t); + + //Return status code + return error; +} + +#endif +#if (SECP224K1_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (secp224k1 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t secp224k1Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi t; + + //Initialize multiple precision integers + mpiInit(&t); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 56 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 32 / MPI_INT_SIZE)); + + //Perform modular reduction + do + { + //Compute T = A13 | A12 | A11 | A10 | A9 | A8 | A7 | 0 + CLEAR_WORD32(&t, 0, 1); + COPY_WORD32(&t, 1, a, 7, 7); + + //Clear A13 | A12 | A11 | A10 | A9 | A8 | A7 + CLEAR_WORD32(a, 7, 7); + + //Compute A = A + T + MPI_CHECK(mpiAdd(a, a, &t)); + //Compute T = T >> 32 + MPI_CHECK(mpiShiftRight(&t, 32)); + //Compute A = A + (6803 * T) + MPI_CHECK(mpiMulInt(&t, &t, 6803)); + MPI_CHECK(mpiAdd(a, a, &t)); + + //Check for end condition + } while(mpiComp(a, p) > 0); + +end: + //Release multiple precision integers + mpiFree(&t); + + //Return status code + return error; +} + +#endif +#if (SECP224R1_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (secp224r1 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t secp224r1Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi s; + Mpi t; + + //Initialize multiple precision integers + mpiInit(&s); + mpiInit(&t); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 56 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&s, 28 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 28 / MPI_INT_SIZE)); + + //Compute T = A6 | A5 | A4 | A3 | A2 | A1 | A0 + COPY_WORD32(&t, 0, a, 0, 7); + + //Compute S1 = A10 | A9 | A8 | A7 | 0 | 0 | 0 + CLEAR_WORD32(&s, 0, 3); + COPY_WORD32(&s, 3, a, 7, 4); + //Compute T = T + S1 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S2 = 0 | A13 | A12 | A11 | 0 | 0 | 0 + CLEAR_WORD32(&s, 0, 3); + COPY_WORD32(&s, 3, a, 11, 3); + CLEAR_WORD32(&s, 6, 1); + //Compute T = T + S2 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute D1 = A13 | A12 | A11 | A10 | A9 | A8 | A7 + COPY_WORD32(&s, 0, a, 7, 7); + //Compute T = T - D1 + MPI_CHECK(mpiSub(&t, &t, &s)); + + //Compute D2 = 0 | 0 | 0 | 0 | A13 | A12 | A11 + COPY_WORD32(&s, 0, a, 11, 3); + CLEAR_WORD32(&s, 3, 4); + //Compute T = T - D2 + MPI_CHECK(mpiSub(&t, &t, &s)); + + //Compute (T + S1 + S2 - D1 - D2) mod p + while(mpiComp(&t, p) >= 0) + { + MPI_CHECK(mpiSub(&t, &t, p)); + } + + while(mpiCompInt(&t, 0) < 0) + { + MPI_CHECK(mpiAdd(&t, &t, p)); + } + + //Save result + MPI_CHECK(mpiCopy(a, &t)); + +end: + //Release multiple precision integers + mpiFree(&s); + mpiFree(&t); + + //Return status code + return error; +} + +#endif +#if (SECP256K1_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (secp256k1 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t secp256k1Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi t; + + //Initialize multiple precision integers + mpiInit(&t); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 64 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 36 / MPI_INT_SIZE)); + + //Perform modular reduction + do + { + //Compute T = A15 | A14 | A13 | A12 | A11 | A10 | A9 | A8 | 0 + CLEAR_WORD32(&t, 0, 1); + COPY_WORD32(&t, 1, a, 8, 8); + + //Clear A15 | A14 | A13 | A12 | A11 | A10 | A9 | A8 + CLEAR_WORD32(a, 8, 8); + + //Compute A = A + T + MPI_CHECK(mpiAdd(a, a, &t)); + //Compute T = T >> 32 + MPI_CHECK(mpiShiftRight(&t, 32)); + //Compute A = A + (977 * T) + MPI_CHECK(mpiMulInt(&t, &t, 977)); + MPI_CHECK(mpiAdd(a, a, &t)); + + //Check for end condition + } while(mpiComp(a, p) > 0); + +end: + //Release multiple precision integers + mpiFree(&t); + + //Return status code + return error; +} + +#endif +#if (SECP256R1_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (secp256r1 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t secp256r1Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi s; + Mpi t; + Mpi b; + + //Initialize multiple precision integers + mpiInit(&s); + mpiInit(&t); + mpiInit(&b); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 64 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&s, 32 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 32 / MPI_INT_SIZE)); + + //Compute T = A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 + COPY_WORD32(&t, 0, a, 0, 8); + + //Compute S1 = A15 | A14 | A13 | A12 | A11 | 0 | 0 | 0 + CLEAR_WORD32(&s, 0, 3); + COPY_WORD32(&s, 3, a, 11, 5); + //Compute T = T + 2 * S1 + MPI_CHECK(mpiAdd(&t, &t, &s)); + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S2 = 0 | A15 | A14 | A13 | A12 | 0 | 0 | 0 + CLEAR_WORD32(&s, 0, 3); + COPY_WORD32(&s, 3, a, 12, 4); + CLEAR_WORD32(&s, 7, 1); + //Compute T = T + 2 * S2 + MPI_CHECK(mpiAdd(&t, &t, &s)); + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S3 = A15 | A14 | 0 | 0 | 0 | A10 | A9 | A8 + COPY_WORD32(&s, 0, a, 8, 3); + CLEAR_WORD32(&s, 3, 3); + COPY_WORD32(&s, 6, a, 14, 2); + //Compute T = T + S3 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S4 = A8 | A13 | A15 | A14 | A13 | A11 | A10 | A9 + COPY_WORD32(&s, 0, a, 9, 3); + COPY_WORD32(&s, 3, a, 13, 3); + COPY_WORD32(&s, 6, a, 13, 1); + COPY_WORD32(&s, 7, a, 8, 1); + //Compute T = T + S4 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute D1 = A10 | A8 | 0 | 0 | 0 | A13 | A12 | A11 + COPY_WORD32(&s, 0, a, 11, 3); + CLEAR_WORD32(&s, 3, 3); + COPY_WORD32(&s, 6, a, 8, 1); + COPY_WORD32(&s, 7, a, 10, 1); + //Compute T = T - D1 + MPI_CHECK(mpiSub(&t, &t, &s)); + + //Compute D2 = A11 | A9 | 0 | 0 | A15 | A14 | A13 | A12 + COPY_WORD32(&s, 0, a, 12, 4); + CLEAR_WORD32(&s, 4, 2); + COPY_WORD32(&s, 6, a, 9, 1); + COPY_WORD32(&s, 7, a, 11, 1); + //Compute T = T - D2 + MPI_CHECK(mpiSub(&t, &t, &s)); + + //Compute D3 = A12 | 0 | A10 | A9 | A8 | A15 | A14 | A13 + COPY_WORD32(&s, 0, a, 13, 3); + COPY_WORD32(&s, 3, a, 8, 3); + CLEAR_WORD32(&s, 6, 1); + COPY_WORD32(&s, 7, a, 12, 1); + //Compute T = T - D3 + MPI_CHECK(mpiSub(&t, &t, &s)); + + //Compute D4 = A13 | 0 | A11 | A10 | A9 | 0 | A15 | A14 + COPY_WORD32(&s, 0, a, 14, 2); + CLEAR_WORD32(&s, 2, 1); + COPY_WORD32(&s, 3, a, 9, 3); + CLEAR_WORD32(&s, 6, 1); + COPY_WORD32(&s, 7, a, 13, 1); + //Compute T = T - D4 + MPI_CHECK(mpiSub(&t, &t, &s)); + + //Compute (T + 2 * S1 + 2 * S2 + S3 + S4 - D1 - D2 - D3 - D4) mod p + while(mpiComp(&t, p) >= 0) + { + MPI_CHECK(mpiSub(&t, &t, p)); + } + + while(mpiCompInt(&t, 0) < 0) + { + MPI_CHECK(mpiAdd(&t, &t, p)); + } + + //Save result + MPI_CHECK(mpiCopy(a, &t)); + +end: + //Release multiple precision integers + mpiFree(&s); + mpiFree(&t); + + //Return status code + return error; +} + +#endif +#if (SECP384R1_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (secp384r1 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t secp384r1Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi s; + Mpi t; + + //Initialize multiple precision integers + mpiInit(&s); + mpiInit(&t); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 96 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&s, 48 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 48 / MPI_INT_SIZE)); + + //Compute T = A11 | A10 | A9 | A8 | A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 + COPY_WORD32(&t, 0, a, 0, 12); + + //Compute S1 = 0 | 0 | 0 | 0 | 0 | A23 | A22 | A21 | 0 | 0 | 0 | 0 + CLEAR_WORD32(&s, 0, 4); + COPY_WORD32(&s, 4, a, 21, 3); + CLEAR_WORD32(&s, 7, 5); + //Compute T = T + 2 * S1 + MPI_CHECK(mpiAdd(&t, &t, &s)); + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S2 = A23 | A22 | A21 | A20 | A19 | A18 | A17 | A16 | A15 | A14 | A13 | A12 + COPY_WORD32(&s, 0, a, 12, 12); + //Compute T = T + S2 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S3 = A20 | A19 | A18 | A17 | A16 | A15 | A14 | A13 | A12 | A23 | A22 | A21 + COPY_WORD32(&s, 0, a, 21, 3); + COPY_WORD32(&s, 3, a, 12, 9); + //Compute T = T + S3 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S4 = A19 | A18 | A17 | A16 | A15 | A14 | A13 | A12 | A20 | 0 | A23 | 0 + CLEAR_WORD32(&s, 0, 1); + COPY_WORD32(&s, 1, a, 23, 1); + CLEAR_WORD32(&s, 2, 1); + COPY_WORD32(&s, 3, a, 20, 1); + COPY_WORD32(&s, 4, a, 12, 8); + //Compute T = T + S4 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S5 = 0 | 0 | 0 | 0 | A23 | A22 | A21 | A20 | 0 | 0 | 0 | 0 + CLEAR_WORD32(&s, 0, 4); + COPY_WORD32(&s, 4, a, 20, 4); + CLEAR_WORD32(&s, 8, 4); + //Compute T = T + S5 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S6 = 0 | 0 | 0 | 0 | 0 | 0 | A23 | A22 | A21 | 0 | 0 | A20 + COPY_WORD32(&s, 0, a, 20, 1); + CLEAR_WORD32(&s, 1, 2); + COPY_WORD32(&s, 3, a, 21, 3); + CLEAR_WORD32(&s, 6, 6); + //Compute T = T + S6 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute D1 = A22 | A21 | A20 | A19 | A18 | A17 | A16 | A15 | A14 | A13 | A12 | A23 + COPY_WORD32(&s, 0, a, 23, 1); + COPY_WORD32(&s, 1, a, 12, 11); + //Compute T = T - D1 + MPI_CHECK(mpiSub(&t, &t, &s)); + + //Compute D2 = 0 | 0 | 0 | 0 | 0 | 0 | 0 | A23 | A22 | A21 | A20 | 0 + CLEAR_WORD32(&s, 0, 1); + COPY_WORD32(&s, 1, a, 20, 4); + CLEAR_WORD32(&s, 5, 7); + //Compute T = T - D2 + MPI_CHECK(mpiSub(&t, &t, &s)); + + //Compute D3 = 0 | 0 | 0 | 0 | 0 | 0 | 0 | A23 | A23 | 0 | 0 | 0 + CLEAR_WORD32(&s, 0, 3); + COPY_WORD32(&s, 3, a, 23, 1); + COPY_WORD32(&s, 4, a, 23, 1); + CLEAR_WORD32(&s, 5, 7); + //Compute T = T - D3 + MPI_CHECK(mpiSub(&t, &t, &s)); + + //Compute (T + 2 * S1 + S2 + S3 + S4 + S5 + S6 - D1 - D2 - D3) mod p + while(mpiComp(&t, p) >= 0) + { + MPI_CHECK(mpiSub(&t, &t, p)); + } + + while(mpiCompInt(&t, 0) < 0) + { + MPI_CHECK(mpiAdd(&t, &t, p)); + } + + //Save result + MPI_CHECK(mpiCopy(a, &t)); + +end: + //Release multiple precision integers + mpiFree(&s); + mpiFree(&t); + + //Return status code + return error; +} + +#endif +#if (SECP521R1_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (secp521r1 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t secp521r1Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi t; + + //Initialize multiple precision integer + mpiInit(&t); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 132 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 68 / MPI_INT_SIZE)); + + //Compute A0 + COPY_WORD32(&t, 0, a, 0, 17); + t.data[16] &= 0x000001FF; + + //Compute A1 + MPI_CHECK(mpiShiftRight(a, 521)); + + //Compute A0 + A1 + MPI_CHECK(mpiAdd(a, a, &t)); + + //Compute (A0 + A1) mod p + while(mpiComp(a, p) >= 0) + { + MPI_CHECK(mpiSub(a, a, p)); + } + +end: + //Release multiple precision integer + mpiFree(&t); + + //Return status code + return error; +} + +#endif +#if (SM2_SUPPORT == ENABLED) + +/** + * @brief Fast modular reduction (SM2 curve) + * @param[in,out] a This function accept an integer less than p^2 as + * input and return (a mod p) as output + * @param[in] p Prime modulus + **/ + +error_t sm2Mod(Mpi *a, const Mpi *p) +{ + error_t error; + Mpi s; + Mpi t; + Mpi b; + + //Initialize multiple precision integers + mpiInit(&s); + mpiInit(&t); + mpiInit(&b); + + //Ajust the size of the integers + MPI_CHECK(mpiGrow(a, 64 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&s, 32 / MPI_INT_SIZE)); + MPI_CHECK(mpiGrow(&t, 32 / MPI_INT_SIZE)); + + //Compute T = A7 | A6 | A5 | A4 | A3 | A2 | A1 | A0 + COPY_WORD32(&t, 0, a, 0, 8); + + //Compute S1 = A15 | A14 | A13 | A12 | A11 | 0 | A9 | A8 + COPY_WORD32(&s, 0, a, 8, 2); + CLEAR_WORD32(&s, 2, 1); + COPY_WORD32(&s, 3, a, 11, 5); + //Compute T = T + S1 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S2 = A8 | A15 | A14 | A13 | A12 | 0 | A10 | A9 + COPY_WORD32(&s, 0, a, 9, 2); + CLEAR_WORD32(&s, 2, 1); + COPY_WORD32(&s, 3, a, 12, 4); + COPY_WORD32(&s, 7, a, 8, 1); + //Compute T = T + S2 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S3 = A9 | A11 | A10 | A9 | A8 | 0 | A11 | A10 + COPY_WORD32(&s, 0, a, 10, 2); + CLEAR_WORD32(&s, 2, 1); + COPY_WORD32(&s, 3, a, 8, 4); + COPY_WORD32(&s, 7, a, 9, 1); + //Compute T = T + S3 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S4 = A10 | 0 | 0 | A15 | A14 | 0 | A12 | A11 + COPY_WORD32(&s, 0, a, 11, 2); + CLEAR_WORD32(&s, 2, 1); + COPY_WORD32(&s, 3, a, 14, 2); + CLEAR_WORD32(&s, 5, 2); + COPY_WORD32(&s, 7, a, 10, 1); + //Compute T = T + S4 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S5 = A11 | 0 | 0 | 0 | A15 | 0 | A13 | A12 + COPY_WORD32(&s, 0, a, 12, 2); + CLEAR_WORD32(&s, 2, 1); + COPY_WORD32(&s, 3, a, 15, 1); + CLEAR_WORD32(&s, 4, 3); + COPY_WORD32(&s, 7, a, 11, 1); + //Compute T = T + S5 + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S6 = A12 | 0 | A15 | A14 | A13 | 0 | A14 | A13 + COPY_WORD32(&s, 0, a, 13, 2); + CLEAR_WORD32(&s, 2, 1); + COPY_WORD32(&s, 3, a, 13, 3); + CLEAR_WORD32(&s, 6, 1); + COPY_WORD32(&s, 7, a, 12, 1); + //Compute T = T + 2*S6 + MPI_CHECK(mpiAdd(&t, &t, &s)); + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S7 = A13 | 0 | 0 | 0 | 0 | 0 | A15 | A14 + COPY_WORD32(&s, 0, a, 14, 2); + CLEAR_WORD32(&s, 2, 5); + COPY_WORD32(&s, 7, a, 13, 1); + //Compute T = T + 2*S7 + MPI_CHECK(mpiAdd(&t, &t, &s)); + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S8 = A14 | 0 | 0 | 0 | 0 | 0 | 0 | A15 + COPY_WORD32(&s, 0, a, 15, 1); + CLEAR_WORD32(&s, 1, 6); + COPY_WORD32(&s, 7, a, 14, 1); + //Compute T = T + 2*S8 + MPI_CHECK(mpiAdd(&t, &t, &s)); + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute S9 = A15 | 0 | 0 | 0 | 0 | 0 | 0 | 0 + CLEAR_WORD32(&s, 0, 7); + COPY_WORD32(&s, 7, a, 15, 1); + //Compute T = T + 2*S9 + MPI_CHECK(mpiAdd(&t, &t, &s)); + MPI_CHECK(mpiAdd(&t, &t, &s)); + + //Compute D1 = 0 | 0 | 0 | 0 | 0 | A8 | 0 | 0 + CLEAR_WORD32(&s, 0, 2); + COPY_WORD32(&s, 2, a, 8, 1); + CLEAR_WORD32(&s, 3, 5); + //Compute T = T - D1 + MPI_CHECK(mpiSub(&t, &t, &s)); + + //Compute D2 = 0 | 0 | 0 | 0 | 0 | A9 | 0 | 0 + CLEAR_WORD32(&s, 0, 2); + COPY_WORD32(&s, 2, a, 9, 1); + CLEAR_WORD32(&s, 3, 5); + //Compute T = T - D2 + MPI_CHECK(mpiSub(&t, &t, &s)); + + //Compute D3 = 0 | 0 | 0 | 0 | 0 | A13 | 0 | 0 + CLEAR_WORD32(&s, 0, 2); + COPY_WORD32(&s, 2, a, 13, 1); + CLEAR_WORD32(&s, 3, 5); + //Compute T = T - D3 + MPI_CHECK(mpiSub(&t, &t, &s)); + + //Compute D4 = 0 | 0 | 0 | 0 | 0 | A14 | 0 | 0 + CLEAR_WORD32(&s, 0, 2); + COPY_WORD32(&s, 2, a, 14, 1); + CLEAR_WORD32(&s, 3, 5); + //Compute T = T - D4 + MPI_CHECK(mpiSub(&t, &t, &s)); + + //Compute (T + S1 + S2 + S3 + S4 + S5 + 2*S6 + 2*S7 + 2*S8 + 2*S9 - D1 - D2 - D3 - D4) mod p + while(mpiComp(&t, p) >= 0) + { + MPI_CHECK(mpiSub(&t, &t, p)); + } + + while(mpiCompInt(&t, 0) < 0) + { + MPI_CHECK(mpiAdd(&t, &t, p)); + } + + //Save result + MPI_CHECK(mpiCopy(a, &t)); + +end: + //Release multiple precision integers + mpiFree(&s); + mpiFree(&t); + + //Return status code + return error; +} + +#endif + +/** + * @brief Get the elliptic curve that matches the specified OID + * @param[in] oid Object identifier + * @param[in] length OID length + * @return Elliptic curve domain parameters + **/ + +const EcCurveInfo *ecGetCurveInfo(const uint8_t *oid, size_t length) +{ + const EcCurveInfo *curveInfo; + + //Invalid parameters? + if(oid == NULL || length == 0) + { + curveInfo = NULL; + } +#if (SECP112R1_SUPPORT == ENABLED) + //secp112r1 elliptic curve? + else if(!oidComp(oid, length, SECP112R1_OID, sizeof(SECP112R1_OID))) + { + curveInfo = SECP112R1_CURVE; + } +#endif +#if (SECP112R2_SUPPORT == ENABLED) + //secp112r2 elliptic curve? + else if(!oidComp(oid, length, SECP112R2_OID, sizeof(SECP112R2_OID))) + { + curveInfo = SECP112R2_CURVE; + } +#endif +#if (SECP128R1_SUPPORT == ENABLED) + //secp128r1 elliptic curve? + else if(!oidComp(oid, length, SECP128R1_OID, sizeof(SECP128R1_OID))) + { + curveInfo = SECP128R1_CURVE; + } +#endif +#if (SECP128R2_SUPPORT == ENABLED) + //secp128r2 elliptic curve? + else if(!oidComp(oid, length, SECP128R2_OID, sizeof(SECP128R2_OID))) + { + curveInfo = SECP128R2_CURVE; + } +#endif +#if (SECP160K1_SUPPORT == ENABLED) + //secp160k1 elliptic curve? + else if(!oidComp(oid, length, SECP160K1_OID, sizeof(SECP160K1_OID))) + { + curveInfo = SECP160K1_CURVE; + } +#endif +#if (SECP160R1_SUPPORT == ENABLED) + //secp160r1 elliptic curve? + else if(!oidComp(oid, length, SECP160R1_OID, sizeof(SECP160R1_OID))) + { + curveInfo = SECP160R1_CURVE; + } +#endif +#if (SECP160R2_SUPPORT == ENABLED) + //secp160r2 elliptic curve? + else if(!oidComp(oid, length, SECP160R2_OID, sizeof(SECP160R2_OID))) + { + curveInfo = SECP160R2_CURVE; + } +#endif +#if (SECP192K1_SUPPORT == ENABLED) + //secp192k1 elliptic curve? + else if(!oidComp(oid, length, SECP192K1_OID, sizeof(SECP192K1_OID))) + { + curveInfo = SECP192K1_CURVE; + } +#endif +#if (SECP192R1_SUPPORT == ENABLED) + //secp192r1 elliptic curve? + else if(!oidComp(oid, length, SECP192R1_OID, sizeof(SECP192R1_OID))) + { + curveInfo = SECP192R1_CURVE; + } +#endif +#if (SECP224K1_SUPPORT == ENABLED) + //secp224k1 elliptic curve? + else if(!oidComp(oid, length, SECP224K1_OID, sizeof(SECP224K1_OID))) + { + curveInfo = SECP224K1_CURVE; + } +#endif +#if (SECP224R1_SUPPORT == ENABLED) + //secp224r1 elliptic curve? + else if(!oidComp(oid, length, SECP224R1_OID, sizeof(SECP224R1_OID))) + { + curveInfo = SECP224R1_CURVE; + } +#endif +#if (SECP256K1_SUPPORT == ENABLED) + //secp256k1 elliptic curve? + else if(!oidComp(oid, length, SECP256K1_OID, sizeof(SECP256K1_OID))) + { + curveInfo = SECP256K1_CURVE; + } +#endif +#if (SECP256R1_SUPPORT == ENABLED) + //secp256r1 elliptic curve? + else if(!oidComp(oid, length, SECP256R1_OID, sizeof(SECP256R1_OID))) + { + curveInfo = SECP256R1_CURVE; + } +#endif +#if (SECP384R1_SUPPORT == ENABLED) + //secp384r1 elliptic curve? + else if(!oidComp(oid, length, SECP384R1_OID, sizeof(SECP384R1_OID))) + { + curveInfo = SECP384R1_CURVE; + } +#endif +#if (SECP521R1_SUPPORT == ENABLED) + //secp521r1 elliptic curve? + else if(!oidComp(oid, length, SECP521R1_OID, sizeof(SECP521R1_OID))) + { + curveInfo = SECP521R1_CURVE; + } +#endif +#if (BRAINPOOLP160R1_SUPPORT == ENABLED) + //brainpoolP160r1 elliptic curve? + else if(!oidComp(oid, length, BRAINPOOLP160R1_OID, sizeof(BRAINPOOLP160R1_OID))) + { + curveInfo = BRAINPOOLP160R1_CURVE; + } +#endif +#if (BRAINPOOLP192R1_SUPPORT == ENABLED) + //brainpoolP192r1 elliptic curve? + else if(!oidComp(oid, length, BRAINPOOLP192R1_OID, sizeof(BRAINPOOLP192R1_OID))) + { + curveInfo = BRAINPOOLP192R1_CURVE; + } +#endif +#if (BRAINPOOLP224R1_SUPPORT == ENABLED) + //brainpoolP224r1 elliptic curve? + else if(!oidComp(oid, length, BRAINPOOLP224R1_OID, sizeof(BRAINPOOLP224R1_OID))) + { + curveInfo = BRAINPOOLP224R1_CURVE; + } +#endif +#if (BRAINPOOLP256R1_SUPPORT == ENABLED) + //brainpoolP256r1 elliptic curve? + else if(!oidComp(oid, length, BRAINPOOLP256R1_OID, sizeof(BRAINPOOLP256R1_OID))) + { + curveInfo = BRAINPOOLP256R1_CURVE; + } +#endif +#if (BRAINPOOLP320R1_SUPPORT == ENABLED) + //brainpoolP320r1 elliptic curve? + else if(!oidComp(oid, length, BRAINPOOLP320R1_OID, sizeof(BRAINPOOLP320R1_OID))) + { + curveInfo = BRAINPOOLP320R1_CURVE; + } +#endif +#if (BRAINPOOLP384R1_SUPPORT == ENABLED) + //brainpoolP384r1 elliptic curve? + else if(!oidComp(oid, length, BRAINPOOLP384R1_OID, sizeof(BRAINPOOLP384R1_OID))) + { + curveInfo = BRAINPOOLP384R1_CURVE; + } +#endif +#if (BRAINPOOLP512R1_SUPPORT == ENABLED) + //brainpoolP512r1 elliptic curve? + else if(!oidComp(oid, length, BRAINPOOLP512R1_OID, sizeof(BRAINPOOLP512R1_OID))) + { + curveInfo = BRAINPOOLP512R1_CURVE; + } +#endif +#if (SM2_SUPPORT == ENABLED) + //SM2 elliptic curve? + else if(!oidComp(oid, length, SM2_OID, sizeof(SM2_OID))) + { + curveInfo = SM2_CURVE; + } +#endif +#if (X25519_SUPPORT == ENABLED) + //Curve25519 elliptic curve? + else if(!oidComp(oid, length, X25519_OID, sizeof(X25519_OID))) + { + curveInfo = X25519_CURVE; + } +#endif +#if (X448_SUPPORT == ENABLED) + //Curve448 elliptic curve? + else if(!oidComp(oid, length, X448_OID, sizeof(X448_OID))) + { + curveInfo = X448_CURVE; + } +#endif +#if (ED25519_SUPPORT == ENABLED) + //Ed25519 elliptic curve? + else if(!oidComp(oid, length, ED25519_OID, sizeof(ED25519_OID))) + { + curveInfo = ED25519_CURVE; + } +#endif +#if (ED448_SUPPORT == ENABLED) + //Ed448 elliptic curve? + else if(!oidComp(oid, length, ED448_OID, sizeof(ED448_OID))) + { + curveInfo = ED448_CURVE; + } +#endif +#if (TC26SIGN512A_SUPPORT == ENABLED) + //tc26Sign512a elliptic curve? + else if (!oidComp(oid, length, TC26SIGN512A_OID, sizeof(TC26SIGN512A_OID))) + { + curveInfo = TC26SIGN512A_CURVE; + } +#endif +#if (TC26SIGN512B_SUPPORT == ENABLED) + //tc26Sign512b elliptic curve? + else if (!oidComp(oid, length, TC26SIGN512B_OID, sizeof(TC26SIGN512B_OID))) + { + curveInfo = TC26SIGN512B_CURVE; + } +#endif + //Unknown identifier? + else + { + curveInfo = NULL; + } + + //Return the elliptic curve domain parameters, if any + return curveInfo; +} + +#endif diff --git a/ecc/ec_curves.h b/ecc/ec_curves.h index 9a97b9d8..87fae5d1 100644 --- a/ecc/ec_curves.h +++ b/ecc/ec_curves.h @@ -7,6 +7,7 @@ * SPDX-License-Identifier: GPL-2.0-or-later * * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * Copyright (c) 2024 Valery Novikov * * This file is part of CycloneCRYPTO Open. * @@ -224,6 +225,20 @@ #error ED448_SUPPORT parameter is not valid #endif +//tc26Sign512a elliptic curve support +#ifndef TC26SIGN512A_SUPPORT +#define TC26SIGN512A_SUPPORT DISABLED +#elif (TC26SIGN512A_SUPPORT != ENABLED && TC26SIGN512A_SUPPORT != DISABLED) +#error TC26SIGN512A_SUPPORT parameter is not valid +#endif + +//tc26Sign512b elliptic curve support +#ifndef TC26SIGN512B_SUPPORT +#define TC26SIGN512B_SUPPORT DISABLED +#elif (TC26SIGN512B_SUPPORT != ENABLED && TC26SIGN512B_SUPPORT != DISABLED) +#error TC26SIGN512B_SUPPORT parameter is not valid +#endif + //Elliptic curves #define SECP112R1_CURVE (&secp112r1Curve) #define SECP112R2_CURVE (&secp112r2Curve) @@ -252,6 +267,9 @@ #define X448_CURVE (&x448Curve) #define ED25519_CURVE (&ed25519Curve) #define ED448_CURVE (&ed448Curve) +// Russian Elliptic curves +#define TC26SIGN512A_CURVE (&tc26Sign512aCurve) +#define TC26SIGN512B_CURVE (&tc26Sign512bCurve) //C++ guard #ifdef __cplusplus @@ -276,7 +294,9 @@ typedef enum EC_CURVE_TYPE_X25519 = 8, EC_CURVE_TYPE_X448 = 9, EC_CURVE_TYPE_ED25519 = 10, - EC_CURVE_TYPE_ED448 = 11 + EC_CURVE_TYPE_ED448 = 11, + EC_CURVE_TYPE_TC26SIGN512A = 12, + EC_CURVE_TYPE_TC26SIGN512B = 13, } EcCurveType; @@ -370,6 +390,9 @@ extern const EcCurveInfo x25519Curve; extern const EcCurveInfo x448Curve; extern const EcCurveInfo ed25519Curve; extern const EcCurveInfo ed448Curve; +// Russian Elliptic curves +extern const EcCurveInfo tc26Sign512aCurve; +extern const EcCurveInfo tc26Sign512bCurve; //Fast modular reduction error_t secp128r1Mod(Mpi *a, const Mpi *p); From baf81621dfa32227e457a4685d1f8fd9f193e863 Mon Sep 17 00:00:00 2001 From: Valerii Novikov <43934124+novval@users.noreply.github.com> Date: Tue, 20 Feb 2024 15:47:35 +0500 Subject: [PATCH 5/8] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 78644fa4..c9f54531 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,8 @@ # CycloneCrypto Cryptographic Library + +Create the directory structure as shown below: +.. +common -- repository contents https://github.com/novval/Common +cyclone_crypto -- repository contents https://github.com/novval/CycloneCRYPTO +demo -- repository contents https://github.com/novval/cyclone_demo From f285636f935d47f2c36c19cc428c908a09a2ea54 Mon Sep 17 00:00:00 2001 From: Novikov Valerii Date: Wed, 21 Feb 2024 12:15:26 +0500 Subject: [PATCH 6/8] Added block cipher kuznyechik as GOST 34.12-2015 --- cipher/cipher_algorithms.h | 13 +- cipher/kuznyechik.c | 523 +++++++++++++++++++++++++++++++++++++ cipher/kuznyechik.h | 115 ++++++++ core/crypto.h | 7 + 4 files changed, 657 insertions(+), 1 deletion(-) create mode 100644 cipher/kuznyechik.c create mode 100644 cipher/kuznyechik.h diff --git a/cipher/cipher_algorithms.h b/cipher/cipher_algorithms.h index 9a6a7a69..c062a5a3 100644 --- a/cipher/cipher_algorithms.h +++ b/cipher/cipher_algorithms.h @@ -154,8 +154,16 @@ #include "cipher/chacha.h" #endif +//KUZNYECHIK cipher support? +#if (KUZNYECHIK_SUPPORT == ENABLED) +#include "cipher/kuznyechik.h" +#endif + + //Maximum block size -#if (RC6_SUPPORT == ENABLED) +#if (KUZNYECHIK_SUPPORT ==ENABLED) +#define MAX_CIPHER_BLOCK_SIZE KUZNYECHIK_BLOCK_SIZE +#elif (RC6_SUPPORT == ENABLED) #define MAX_CIPHER_BLOCK_SIZE RC6_BLOCK_SIZE #elif (CAST256_SUPPORT == ENABLED) #define MAX_CIPHER_BLOCK_SIZE CAST256_BLOCK_SIZE @@ -273,6 +281,9 @@ typedef union #if (ZUC_SUPPORT == ENABLED) ZucContext zucContext; #endif +#if (KUZNYECHIK_SUPPORT == ENABLED) + KuznyechikContext kuznyechikContext; +#endif } CipherContext; diff --git a/cipher/kuznyechik.c b/cipher/kuznyechik.c new file mode 100644 index 00000000..293084c0 --- /dev/null +++ b/cipher/kuznyechik.c @@ -0,0 +1,523 @@ +/** + * @file kuznyechik.c + * @brief Kuznyechik 128bit cipher as specified in GOST R 34-12.2015 + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2015 Markku-Juhani O. Saarinen + * Copyright (c) 2017 Vlasta Vesely + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * Copyright (c) 2024 Valery Novikov + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @section Description + * + * This implementation is Saarinen's code modified in order to allow usage + * as Linux Kernel module. The original code can be found on Github: + * https://github.com/mjosaarinen/kuznechik/blob/master/kuznechik_128bit.c + * + * In order to use it as Kernel module, original SSE optimization has been + * replaced by operations on 64bit integers. Although it is slower than + * original version, it is still faster than (or equal to) another portable + * implementations we have tested. + * + * @author Valery Novikov + * @version 2.4.0 + **/ + +/** + * TODO: + * OIDs + * pem_common + * pkcs4_common + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL CRYPTO_TRACE_LEVEL + +//Dependencies +#include "core/crypto.h" +#include "cipher/kuznyechik.h" + +//Check crypto library configuration +#if (KUZNYECHIK_SUPPORT == ENABLED) + +/* S-box */ +static const uint8_t kuz_pi[256] = { + 0xFC, 0xEE, 0xDD, 0x11, 0xCF, 0x6E, 0x31, 0x16, + 0xFB, 0xC4, 0xFA, 0xDA, 0x23, 0xC5, 0x04, 0x4D, + 0xE9, 0x77, 0xF0, 0xDB, 0x93, 0x2E, 0x99, 0xBA, + 0x17, 0x36, 0xF1, 0xBB, 0x14, 0xCD, 0x5F, 0xC1, + 0xF9, 0x18, 0x65, 0x5A, 0xE2, 0x5C, 0xEF, 0x21, + 0x81, 0x1C, 0x3C, 0x42, 0x8B, 0x01, 0x8E, 0x4F, + 0x05, 0x84, 0x02, 0xAE, 0xE3, 0x6A, 0x8F, 0xA0, + 0x06, 0x0B, 0xED, 0x98, 0x7F, 0xD4, 0xD3, 0x1F, + 0xEB, 0x34, 0x2C, 0x51, 0xEA, 0xC8, 0x48, 0xAB, + 0xF2, 0x2A, 0x68, 0xA2, 0xFD, 0x3A, 0xCE, 0xCC, + 0xB5, 0x70, 0x0E, 0x56, 0x08, 0x0C, 0x76, 0x12, + 0xBF, 0x72, 0x13, 0x47, 0x9C, 0xB7, 0x5D, 0x87, + 0x15, 0xA1, 0x96, 0x29, 0x10, 0x7B, 0x9A, 0xC7, + 0xF3, 0x91, 0x78, 0x6F, 0x9D, 0x9E, 0xB2, 0xB1, + 0x32, 0x75, 0x19, 0x3D, 0xFF, 0x35, 0x8A, 0x7E, + 0x6D, 0x54, 0xC6, 0x80, 0xC3, 0xBD, 0x0D, 0x57, + 0xDF, 0xF5, 0x24, 0xA9, 0x3E, 0xA8, 0x43, 0xC9, + 0xD7, 0x79, 0xD6, 0xF6, 0x7C, 0x22, 0xB9, 0x03, + 0xE0, 0x0F, 0xEC, 0xDE, 0x7A, 0x94, 0xB0, 0xBC, + 0xDC, 0xE8, 0x28, 0x50, 0x4E, 0x33, 0x0A, 0x4A, + 0xA7, 0x97, 0x60, 0x73, 0x1E, 0x00, 0x62, 0x44, + 0x1A, 0xB8, 0x38, 0x82, 0x64, 0x9F, 0x26, 0x41, + 0xAD, 0x45, 0x46, 0x92, 0x27, 0x5E, 0x55, 0x2F, + 0x8C, 0xA3, 0xA5, 0x7D, 0x69, 0xD5, 0x95, 0x3B, + 0x07, 0x58, 0xB3, 0x40, 0x86, 0xAC, 0x1D, 0xF7, + 0x30, 0x37, 0x6B, 0xE4, 0x88, 0xD9, 0xE7, 0x89, + 0xE1, 0x1B, 0x83, 0x49, 0x4C, 0x3F, 0xF8, 0xFE, + 0x8D, 0x53, 0xAA, 0x90, 0xCA, 0xD8, 0x85, 0x61, + 0x20, 0x71, 0x67, 0xA4, 0x2D, 0x2B, 0x09, 0x5B, + 0xCB, 0x9B, 0x25, 0xD0, 0xBE, 0xE5, 0x6C, 0x52, + 0x59, 0xA6, 0x74, 0xD2, 0xE6, 0xF4, 0xB4, 0xC0, + 0xD1, 0x66, 0xAF, 0xC2, 0x39, 0x4B, 0x63, 0xB6, +}; + +/* Inverse S-box */ +static const uint8_t kuz_pi_inv[256] = { + 0xA5, 0x2D, 0x32, 0x8F, 0x0E, 0x30, 0x38, 0xC0, + 0x54, 0xE6, 0x9E, 0x39, 0x55, 0x7E, 0x52, 0x91, + 0x64, 0x03, 0x57, 0x5A, 0x1C, 0x60, 0x07, 0x18, + 0x21, 0x72, 0xA8, 0xD1, 0x29, 0xC6, 0xA4, 0x3F, + 0xE0, 0x27, 0x8D, 0x0C, 0x82, 0xEA, 0xAE, 0xB4, + 0x9A, 0x63, 0x49, 0xE5, 0x42, 0xE4, 0x15, 0xB7, + 0xC8, 0x06, 0x70, 0x9D, 0x41, 0x75, 0x19, 0xC9, + 0xAA, 0xFC, 0x4D, 0xBF, 0x2A, 0x73, 0x84, 0xD5, + 0xC3, 0xAF, 0x2B, 0x86, 0xA7, 0xB1, 0xB2, 0x5B, + 0x46, 0xD3, 0x9F, 0xFD, 0xD4, 0x0F, 0x9C, 0x2F, + 0x9B, 0x43, 0xEF, 0xD9, 0x79, 0xB6, 0x53, 0x7F, + 0xC1, 0xF0, 0x23, 0xE7, 0x25, 0x5E, 0xB5, 0x1E, + 0xA2, 0xDF, 0xA6, 0xFE, 0xAC, 0x22, 0xF9, 0xE2, + 0x4A, 0xBC, 0x35, 0xCA, 0xEE, 0x78, 0x05, 0x6B, + 0x51, 0xE1, 0x59, 0xA3, 0xF2, 0x71, 0x56, 0x11, + 0x6A, 0x89, 0x94, 0x65, 0x8C, 0xBB, 0x77, 0x3C, + 0x7B, 0x28, 0xAB, 0xD2, 0x31, 0xDE, 0xC4, 0x5F, + 0xCC, 0xCF, 0x76, 0x2C, 0xB8, 0xD8, 0x2E, 0x36, + 0xDB, 0x69, 0xB3, 0x14, 0x95, 0xBE, 0x62, 0xA1, + 0x3B, 0x16, 0x66, 0xE9, 0x5C, 0x6C, 0x6D, 0xAD, + 0x37, 0x61, 0x4B, 0xB9, 0xE3, 0xBA, 0xF1, 0xA0, + 0x85, 0x83, 0xDA, 0x47, 0xC5, 0xB0, 0x33, 0xFA, + 0x96, 0x6F, 0x6E, 0xC2, 0xF6, 0x50, 0xFF, 0x5D, + 0xA9, 0x8E, 0x17, 0x1B, 0x97, 0x7D, 0xEC, 0x58, + 0xF7, 0x1F, 0xFB, 0x7C, 0x09, 0x0D, 0x7A, 0x67, + 0x45, 0x87, 0xDC, 0xE8, 0x4F, 0x1D, 0x4E, 0x04, + 0xEB, 0xF8, 0xF3, 0x3E, 0x3D, 0xBD, 0x8A, 0x88, + 0xDD, 0xCD, 0x0B, 0x13, 0x98, 0x02, 0x93, 0x80, + 0x90, 0xD0, 0x24, 0x34, 0xCB, 0xED, 0xF4, 0xCE, + 0x99, 0x10, 0x44, 0x40, 0x92, 0x3A, 0x01, 0x26, + 0x12, 0x1A, 0x48, 0x68, 0xF5, 0x81, 0x8B, 0xC7, + 0xD6, 0x20, 0x0A, 0x08, 0x00, 0x4C, 0xD7, 0x74 +}; + +/* Linear vector from sect 5.1.2 */ +static const uint8_t kuz_lvec[16] = { + 0x94, 0x20, 0x85, 0x10, 0xC2, 0xC0, 0x01, 0xFB, + 0x01, 0xC0, 0xC2, 0x10, 0x85, 0x20, 0x94, 0x01 +}; + +static int kuz_initialized = 0; + +/* Lookup tables */ +static uint64_t kuz_pil_enc[16][256][2]; +static uint64_t kuz_l_dec[16][256][2]; +static uint64_t kuz_pil_dec[16][256][2]; + +//Common interface for encryption algorithms +const CipherAlgo kuznyechikCipherAlgo = +{ + "Kuznyechik", + sizeof(KuznyechikContext), + CIPHER_ALGO_TYPE_BLOCK, + KUZNYECHIK_BLOCK_SIZE, + (CipherAlgoInit)kuznyechikInit, + NULL, + NULL, + (CipherAlgoEncryptBlock)kuznyechikEncryptBlock, + (CipherAlgoDecryptBlock)kuznyechikDecryptBlock, + (CipherAlgoDeinit)kuznyechikDeinit +}; + + +/* poly multiplication mod p(x) = x^8 + x^7 + x^6 + x + 1 */ +static uint8_t kuz_mul_gf256(uint8_t x, uint8_t y) +{ + uint8_t z = 0; + while (y) { + if (y & 1) z ^= x; + x = (x << 1) ^ (x & 0x80 ? 0xC3 : 0x00); + y >>= 1; + } + return z; +} + +/* (slow) linear operation l */ +static void kuz_l(w128_t *w) +{ + int i, j; + uint8_t x; + for (j = 0; j < 16; j++) { + /* An LFSR with 16 elements from GF(2^8) */ + x = w->b[15]; /* since lvec[15] = 1 */ + for (i = 14; i >= 0; i--) { + w->b[i + 1] = w->b[i]; + x ^= kuz_mul_gf256(w->b[i], kuz_lvec[i]); + } + w->b[0] = x; + } +} + +/* inverse of linear operation l */ +static void kuz_l_inv(w128_t *w) +{ + int i, j; + uint8_t x; + for (j = 0; j < 16; j++) { + x = w->b[0]; + for (i = 0; i < 15; i++) { + w->b[i] = w->b[i + 1]; + x ^= kuz_mul_gf256(w->b[i], kuz_lvec[i]); + } + w->b[15] = x; + } +} + +/* initialize lookup tables */ +static void kuz_init() +{ + int i, j; + w128_t x; + + for (i = 0; i < 16; i++) { + for (j = 0; j < 256; j++) { + x.q[0] = 0; + x.q[1] = 0; + x.b[i] = kuz_pi[j]; + kuz_l(&x); + + kuz_pil_enc[i][j][0] = x.q[0]; + kuz_pil_enc[i][j][1] = x.q[1]; + + x.q[0] = 0; + x.q[1] = 0; + x.b[i] = j; // kuz_pi[j]; + kuz_l_inv(&x); + + kuz_l_dec[i][j][0] = x.q[0]; + kuz_l_dec[i][j][1] = x.q[1]; + + x.q[0] = 0; + x.q[1] = 0; + x.b[i] = kuz_pi_inv[j]; + kuz_l_inv(&x); + + kuz_pil_dec[i][j][0] = x.q[0]; + kuz_pil_dec[i][j][1] = x.q[1]; + } + } + kuz_initialized = 1; +} + +/* +//AES128-ECB OID (2.16.840.1.101.3.4.1.1) +const uint8_t AES128_ECB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x01}; +//AES128-CBC OID (2.16.840.1.101.3.4.1.2) +const uint8_t AES128_CBC_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02}; +//AES128-OFB OID (2.16.840.1.101.3.4.1.3) +const uint8_t AES128_OFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x03}; +//AES128-CFB OID (2.16.840.1.101.3.4.1.4) +const uint8_t AES128_CFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x04}; +//AES128-GCM OID (2.16.840.1.101.3.4.1.6) +const uint8_t AES128_GCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x06}; +//AES128-CCM OID (2.16.840.1.101.3.4.1.7) +const uint8_t AES128_CCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x07}; + +//AES192-ECB OID (2.16.840.1.101.3.4.1.21) +const uint8_t AES192_ECB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x15}; +//AES192-CBC OID (2.16.840.1.101.3.4.1.22) +const uint8_t AES192_CBC_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16}; +//AES192-OFB OID (2.16.840.1.101.3.4.1.23) +const uint8_t AES192_OFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x17}; +//AES192-CFB OID (2.16.840.1.101.3.4.1.24) +const uint8_t AES192_CFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x18}; +//AES192-GCM OID (2.16.840.1.101.3.4.1.26) +const uint8_t AES192_GCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x1A}; +//AES192-CCM OID (2.16.840.1.101.3.4.1.27) +const uint8_t AES192_CCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x1B}; + +//AES256-ECB OID (2.16.840.1.101.3.4.1.41) +const uint8_t AES256_ECB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x29}; +//AES256-CBC OID (2.16.840.1.101.3.4.1.42) +const uint8_t AES256_CBC_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2A}; +//AES256-OFB OID (2.16.840.1.101.3.4.1.43) +const uint8_t AES256_OFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2B}; +//AES256-CFB OID (2.16.840.1.101.3.4.1.44) +const uint8_t AES256_CFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2C}; +//AES256-GCM OID (2.16.840.1.101.3.4.1.46) +const uint8_t AES256_GCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2E}; +//AES256-CCM OID (2.16.840.1.101.3.4.1.47) +const uint8_t AES256_CCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2F}; +*/ + + +/** + * @brief Key expansion + * @param[in] context Pointer to the KUZNYECHIK context to initialize + * @param[in] key Pointer to the key + * @param[in] keyLen Length of the key + * @return Error code + **/ + +__weak_func error_t kuznyechikInit(KuznyechikContext *context, const uint8_t *key, size_t keyLen) +{ + int i, j; + w128_t c, x, y, z; + + //Check parameters + if(context == NULL || key == NULL) + return ERROR_INVALID_PARAMETER; + + //Check the length of the key + if(keyLen != 16) + //Report an error + return ERROR_INVALID_KEY_LENGTH; + + if (!kuz_initialized) + kuz_init(); + + for (i = 0; i < 16; i++) { + /* this will be have to changed for little-endian systems */ + x.b[i] = key[i]; + y.b[i] = key[i + 16]; + } + + context->ek[0].q[0] = x.q[0]; + context->ek[0].q[1] = x.q[1]; + context->ek[1].q[0] = y.q[0]; + context->ek[1].q[1] = y.q[1]; + + for (i = 1; i <= 32; i++) { + /* C Value */ + c.q[0] = 0; + c.q[1] = 0; + c.b[15] = i; /* load round in lsb */ + kuz_l(&c); + + z.q[0] = x.q[0] ^ c.q[0]; + z.q[1] = x.q[1] ^ c.q[1]; + for (j = 0; j < 16; j++) + z.b[j] = kuz_pi[z.b[j]]; + kuz_l(&z); + z.q[0] ^= y.q[0]; + z.q[1] ^= y.q[1]; + + y.q[0] = x.q[0]; + y.q[1] = x.q[1]; + + x.q[0] = z.q[0]; + x.q[1] = z.q[1]; + + if ((i & 7) == 0) { + context->ek[(i >> 2)].q[0] = x.q[0]; + context->ek[(i >> 2)].q[1] = x.q[1]; + context->ek[(i >> 2) + 1].q[0] = y.q[0]; + context->ek[(i >> 2) + 1].q[1] = y.q[1]; + } + } + for (i = 0; i < 10; i++) { + context->dk[i] = context->ek[i]; + if (i) kuz_l_inv(&context->dk[i]); + } + //No error to report + return NO_ERROR; +} + + +/** + * @brief Encrypt a 16-byte block using KUZNYECHIK algorithm + * @param[in] context Pointer to the KUZNYECHIK context + * @param[in] input Plaintext block to encrypt + * @param[out] output Ciphertext block resulting from encryption + **/ + +void kuznyechikEncryptBlock(KuznyechikContext *context, const uint8_t *input, uint8_t *output) +{ + unsigned int i; + + w128_t x, y; + x.q[0] = ((uint64_t *)input)[0]; + x.q[1] = ((uint64_t *)input)[1]; + + for (i = 0; i < 9; i++) { + x.q[0] ^= context->ek[i].q[0]; + x.q[1] ^= context->ek[i].q[1]; + y.q[0] = kuz_pil_enc[0][((uint8_t *)&x)[0]][0] ^ + kuz_pil_enc[1][((uint8_t *)&x)[1]][0] ^ + kuz_pil_enc[2][((uint8_t *)&x)[2]][0] ^ + kuz_pil_enc[3][((uint8_t *)&x)[3]][0] ^ + kuz_pil_enc[4][((uint8_t *)&x)[4]][0] ^ + kuz_pil_enc[5][((uint8_t *)&x)[5]][0] ^ + kuz_pil_enc[6][((uint8_t *)&x)[6]][0] ^ + kuz_pil_enc[7][((uint8_t *)&x)[7]][0] ^ + kuz_pil_enc[8][((uint8_t *)&x)[8]][0] ^ + kuz_pil_enc[9][((uint8_t *)&x)[9]][0] ^ + kuz_pil_enc[10][((uint8_t *)&x)[10]][0] ^ + kuz_pil_enc[11][((uint8_t *)&x)[11]][0] ^ + kuz_pil_enc[12][((uint8_t *)&x)[12]][0] ^ + kuz_pil_enc[13][((uint8_t *)&x)[13]][0] ^ + kuz_pil_enc[14][((uint8_t *)&x)[14]][0] ^ + kuz_pil_enc[15][((uint8_t *)&x)[15]][0]; + y.q[1] = kuz_pil_enc[0][((uint8_t *)&x)[0]][1] ^ + kuz_pil_enc[1][((uint8_t *)&x)[1]][1] ^ + kuz_pil_enc[2][((uint8_t *)&x)[2]][1] ^ + kuz_pil_enc[3][((uint8_t *)&x)[3]][1] ^ + kuz_pil_enc[4][((uint8_t *)&x)[4]][1] ^ + kuz_pil_enc[5][((uint8_t *)&x)[5]][1] ^ + kuz_pil_enc[6][((uint8_t *)&x)[6]][1] ^ + kuz_pil_enc[7][((uint8_t *)&x)[7]][1] ^ + kuz_pil_enc[8][((uint8_t *)&x)[8]][1] ^ + kuz_pil_enc[9][((uint8_t *)&x)[9]][1] ^ + kuz_pil_enc[10][((uint8_t *)&x)[10]][1] ^ + kuz_pil_enc[11][((uint8_t *)&x)[11]][1] ^ + kuz_pil_enc[12][((uint8_t *)&x)[12]][1] ^ + kuz_pil_enc[13][((uint8_t *)&x)[13]][1] ^ + kuz_pil_enc[14][((uint8_t *)&x)[14]][1] ^ + kuz_pil_enc[15][((uint8_t *)&x)[15]][1]; + x = y; + } + ((uint64_t *)output)[0] = x.q[0] ^ context->ek[9].q[0]; + ((uint64_t *)output)[1] = x.q[1] ^ context->ek[9].q[1]; +} + + +/** + * @brief Decypt a 16-byte block using KUZNYECHIK algorithm + * @param[in] context Pointer to the KUZNYECHIK context + * @param[in] input Plaintext block to encrypt + * @param[out] output Ciphertext block resulting from encryption + **/ + +void kuznyechikDecryptBlock(KuznyechikContext *context, const uint8_t *input, uint8_t *output) +{ + unsigned int i; + + w128_t x, y; + x.q[0] = ((uint64_t *)input)[0]; + x.q[1] = ((uint64_t *)input)[1]; + y.q[0] = kuz_l_dec[0][((uint8_t *)&x)[0]][0] ^ + kuz_l_dec[1][((uint8_t *)&x)[1]][0] ^ + kuz_l_dec[2][((uint8_t *)&x)[2]][0] ^ + kuz_l_dec[3][((uint8_t *)&x)[3]][0] ^ + kuz_l_dec[4][((uint8_t *)&x)[4]][0] ^ + kuz_l_dec[5][((uint8_t *)&x)[5]][0] ^ + kuz_l_dec[6][((uint8_t *)&x)[6]][0] ^ + kuz_l_dec[7][((uint8_t *)&x)[7]][0] ^ + kuz_l_dec[8][((uint8_t *)&x)[8]][0] ^ + kuz_l_dec[9][((uint8_t *)&x)[9]][0] ^ + kuz_l_dec[10][((uint8_t *)&x)[10]][0] ^ + kuz_l_dec[11][((uint8_t *)&x)[11]][0] ^ + kuz_l_dec[12][((uint8_t *)&x)[12]][0] ^ + kuz_l_dec[13][((uint8_t *)&x)[13]][0] ^ + kuz_l_dec[14][((uint8_t *)&x)[14]][0] ^ + kuz_l_dec[15][((uint8_t *)&x)[15]][0]; + y.q[1] = kuz_l_dec[0][((uint8_t *)&x)[0]][1] ^ + kuz_l_dec[1][((uint8_t *)&x)[1]][1] ^ + kuz_l_dec[2][((uint8_t *)&x)[2]][1] ^ + kuz_l_dec[3][((uint8_t *)&x)[3]][1] ^ + kuz_l_dec[4][((uint8_t *)&x)[4]][1] ^ + kuz_l_dec[5][((uint8_t *)&x)[5]][1] ^ + kuz_l_dec[6][((uint8_t *)&x)[6]][1] ^ + kuz_l_dec[7][((uint8_t *)&x)[7]][1] ^ + kuz_l_dec[8][((uint8_t *)&x)[8]][1] ^ + kuz_l_dec[9][((uint8_t *)&x)[9]][1] ^ + kuz_l_dec[10][((uint8_t *)&x)[10]][1] ^ + kuz_l_dec[11][((uint8_t *)&x)[11]][1] ^ + kuz_l_dec[12][((uint8_t *)&x)[12]][1] ^ + kuz_l_dec[13][((uint8_t *)&x)[13]][1] ^ + kuz_l_dec[14][((uint8_t *)&x)[14]][1] ^ + kuz_l_dec[15][((uint8_t *)&x)[15]][1]; + x = y; + + for (i = 9; i > 1; i--) { + x.q[0] ^= context->dk[i].q[0]; + x.q[1] ^= context->dk[i].q[1]; + y.q[0] = kuz_pil_dec[0][((uint8_t *)&x)[0]][0] ^ + kuz_pil_dec[1][((uint8_t *)&x)[1]][0] ^ + kuz_pil_dec[2][((uint8_t *)&x)[2]][0] ^ + kuz_pil_dec[3][((uint8_t *)&x)[3]][0] ^ + kuz_pil_dec[4][((uint8_t *)&x)[4]][0] ^ + kuz_pil_dec[5][((uint8_t *)&x)[5]][0] ^ + kuz_pil_dec[6][((uint8_t *)&x)[6]][0] ^ + kuz_pil_dec[7][((uint8_t *)&x)[7]][0] ^ + kuz_pil_dec[8][((uint8_t *)&x)[8]][0] ^ + kuz_pil_dec[9][((uint8_t *)&x)[9]][0] ^ + kuz_pil_dec[10][((uint8_t *)&x)[10]][0] ^ + kuz_pil_dec[11][((uint8_t *)&x)[11]][0] ^ + kuz_pil_dec[12][((uint8_t *)&x)[12]][0] ^ + kuz_pil_dec[13][((uint8_t *)&x)[13]][0] ^ + kuz_pil_dec[14][((uint8_t *)&x)[14]][0] ^ + kuz_pil_dec[15][((uint8_t *)&x)[15]][0]; + y.q[1] = kuz_pil_dec[0][((uint8_t *)&x)[0]][1] ^ + kuz_pil_dec[1][((uint8_t *)&x)[1]][1] ^ + kuz_pil_dec[2][((uint8_t *)&x)[2]][1] ^ + kuz_pil_dec[3][((uint8_t *)&x)[3]][1] ^ + kuz_pil_dec[4][((uint8_t *)&x)[4]][1] ^ + kuz_pil_dec[5][((uint8_t *)&x)[5]][1] ^ + kuz_pil_dec[6][((uint8_t *)&x)[6]][1] ^ + kuz_pil_dec[7][((uint8_t *)&x)[7]][1] ^ + kuz_pil_dec[8][((uint8_t *)&x)[8]][1] ^ + kuz_pil_dec[9][((uint8_t *)&x)[9]][1] ^ + kuz_pil_dec[10][((uint8_t *)&x)[10]][1] ^ + kuz_pil_dec[11][((uint8_t *)&x)[11]][1] ^ + kuz_pil_dec[12][((uint8_t *)&x)[12]][1] ^ + kuz_pil_dec[13][((uint8_t *)&x)[13]][1] ^ + kuz_pil_dec[14][((uint8_t *)&x)[14]][1] ^ + kuz_pil_dec[15][((uint8_t *)&x)[15]][1]; + x = y; + } + x.q[0] ^= context->dk[1].q[0]; + x.q[1] ^= context->dk[1].q[1]; + for (i = 0; i < 16; i++) { + ((uint8_t *)&x)[i] = kuz_pi_inv[((uint8_t *)&x)[i]]; + } + x.q[0] ^= context->dk[0].q[0]; + x.q[1] ^= context->dk[0].q[1]; + + ((uint64_t *)output)[0] = x.q[0]; + ((uint64_t *)output)[1] = x.q[1]; +} + + +/** + * @brief Release KUZNYECHIK context + * @param[in] context Pointer to the KUZNYECHIK context + **/ + +__weak_func void kuznyechikDeinit(KuznyechikContext *context) +{ + //Clear KUZNYECHIK context + osMemset(context, 0, sizeof(KuznyechikContext)); +} + +#endif diff --git a/cipher/kuznyechik.h b/cipher/kuznyechik.h new file mode 100644 index 00000000..b2e043df --- /dev/null +++ b/cipher/kuznyechik.h @@ -0,0 +1,115 @@ +/** + * @file kuznyechik.h + * @brief Kuznyechik 128bit cipher as specified in GOST R 34-12.2015 + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2015 Markku-Juhani O. Saarinen + * Copyright (c) 2017 Vlasta Vesely + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * Copyright (c) 2024 Valery Novikov + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Valery Novikov + * @version 2.4.0 + **/ + +#ifndef _KUZNYECHIK_H +#define _KUZNYECHIK_H + +//Dependencies +#include "core/crypto.h" + +//Application specific context +#ifndef KUZNYECHIK_PRIVATE_CONTEXT + #define KUZNYECHIK_PRIVATE_CONTEXT +#endif + +//KUZNYECHIK block size +#define KUZNYECHIK_BLOCK_SIZE 16 +//Common interface for encryption algorithms +#define KUZNYECHIK_CIPHER_ALGO (&kuznyechikCipherAlgo) + +//C++ guard +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @brief KUZNYECHIK internal union representing 128-bit data structure. +**/ + +typedef union +{ + uint64_t q[2]; + uint8_t b[16]; +} w128_t; + + +/** + * @brief KUZNYECHIK algorithm context + **/ + +typedef struct +{ + uint_t nr; + w128_t ek[60]; + w128_t dk[60]; + KUZNYECHIK_PRIVATE_CONTEXT +} KuznyechikContext; + +/* +//KUZNYECHIK related constants +extern const uint8_t AES128_ECB_OID[9]; +extern const uint8_t AES128_CBC_OID[9]; +extern const uint8_t AES128_OFB_OID[9]; +extern const uint8_t AES128_CFB_OID[9]; +extern const uint8_t AES128_GCM_OID[9]; +extern const uint8_t AES128_CCM_OID[9]; +extern const uint8_t AES192_ECB_OID[9]; +extern const uint8_t AES192_CBC_OID[9]; +extern const uint8_t AES192_OFB_OID[9]; +extern const uint8_t AES192_CFB_OID[9]; +extern const uint8_t AES192_GCM_OID[9]; +extern const uint8_t AES192_CCM_OID[9]; +extern const uint8_t AES256_ECB_OID[9]; +extern const uint8_t AES256_CBC_OID[9]; +extern const uint8_t AES256_OFB_OID[9]; +extern const uint8_t AES256_CFB_OID[9]; +extern const uint8_t AES256_GCM_OID[9]; +extern const uint8_t AES256_CCM_OID[9]; +*/ +extern const CipherAlgo kuznyechikCipherAlgo; + +//KUZNYECHIK related functions +error_t kuznyechikInit(KuznyechikContext *context, const uint8_t *key, size_t keyLen); + +void kuznyechikEncryptBlock(KuznyechikContext *context, const uint8_t *input, uint8_t *output); + +void kuznyechikDecryptBlock(KuznyechikContext *context, const uint8_t *input, uint8_t *output); + +void kuznyechikDeinit(KuznyechikContext *context); + +//C++ guard +#ifdef __cplusplus +} +#endif + +#endif diff --git a/core/crypto.h b/core/crypto.h index 5e9f6fbb..50883c7f 100644 --- a/core/crypto.h +++ b/core/crypto.h @@ -522,6 +522,13 @@ #error TEA_SUPPORT parameter is not valid #endif +//KUZNYECHIK block cipher support +#ifndef KUZNYECHIK_SUPPORT +#define KUZNYECHIK_SUPPORT DISABLED +#elif (KUZNYECHIK_SUPPORT != ENABLED && KUZNYECHIK_SUPPORT != DISABLED) +#error KUZNYECHIK_SUPPORT parameter is not valid +#endif + //XTEA block cipher support #ifndef XTEA_SUPPORT #define XTEA_SUPPORT DISABLED From 76943b521bab7c855d6492590630a767d514f6a3 Mon Sep 17 00:00:00 2001 From: Novikov Valerii Date: Thu, 22 Feb 2024 11:31:46 +0500 Subject: [PATCH 7/8] Added kuznyechik_algo8.c - algorithm without big tables --- cipher/kuznyechik_algo8.c | 399 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 cipher/kuznyechik_algo8.c diff --git a/cipher/kuznyechik_algo8.c b/cipher/kuznyechik_algo8.c new file mode 100644 index 00000000..8b391839 --- /dev/null +++ b/cipher/kuznyechik_algo8.c @@ -0,0 +1,399 @@ +/** + * @file kuznyechik.c + * @brief Kuznyechik 128bit cipher as specified in GOST R 34-12.2015 + * + * @section License + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (c) 2015 Markku-Juhani O. Saarinen + * Copyright (c) 2017 Vlasta Vesely + * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved. + * Copyright (c) 2024 Valery Novikov + * + * This file is part of CycloneCRYPTO Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @section Description + * + * This implementation is Saarinen's code kuznechik_8bit.c + * with small optimize. The original code can be found on Github: + * https://github.com/mjosaarinen/kuznechik/blob/master/kuznechik_8bit.c + * + * @author Valery Novikov + * @version 2.4.0 + **/ + +/** + * TODO: + * OIDs + * pem_common + * pkcs4_common + **/ + +//Switch to the appropriate trace level +#define TRACE_LEVEL CRYPTO_TRACE_LEVEL + +//Dependencies +#include "core/crypto.h" +#include "cipher/kuznyechik.h" + +//Check crypto library configuration +#if (KUZNYECHIK_SUPPORT == ENABLED) + +// The S-Box from section 5.1.1 + +static const uint8_t kuz_pi[0x100] = { + 0xFC, 0xEE, 0xDD, 0x11, 0xCF, 0x6E, 0x31, 0x16, // 00..07 + 0xFB, 0xC4, 0xFA, 0xDA, 0x23, 0xC5, 0x04, 0x4D, // 08..0F + 0xE9, 0x77, 0xF0, 0xDB, 0x93, 0x2E, 0x99, 0xBA, // 10..17 + 0x17, 0x36, 0xF1, 0xBB, 0x14, 0xCD, 0x5F, 0xC1, // 18..1F + 0xF9, 0x18, 0x65, 0x5A, 0xE2, 0x5C, 0xEF, 0x21, // 20..27 + 0x81, 0x1C, 0x3C, 0x42, 0x8B, 0x01, 0x8E, 0x4F, // 28..2F + 0x05, 0x84, 0x02, 0xAE, 0xE3, 0x6A, 0x8F, 0xA0, // 30..37 + 0x06, 0x0B, 0xED, 0x98, 0x7F, 0xD4, 0xD3, 0x1F, // 38..3F + 0xEB, 0x34, 0x2C, 0x51, 0xEA, 0xC8, 0x48, 0xAB, // 40..47 + 0xF2, 0x2A, 0x68, 0xA2, 0xFD, 0x3A, 0xCE, 0xCC, // 48..4F + 0xB5, 0x70, 0x0E, 0x56, 0x08, 0x0C, 0x76, 0x12, // 50..57 + 0xBF, 0x72, 0x13, 0x47, 0x9C, 0xB7, 0x5D, 0x87, // 58..5F + 0x15, 0xA1, 0x96, 0x29, 0x10, 0x7B, 0x9A, 0xC7, // 60..67 + 0xF3, 0x91, 0x78, 0x6F, 0x9D, 0x9E, 0xB2, 0xB1, // 68..6F + 0x32, 0x75, 0x19, 0x3D, 0xFF, 0x35, 0x8A, 0x7E, // 70..77 + 0x6D, 0x54, 0xC6, 0x80, 0xC3, 0xBD, 0x0D, 0x57, // 78..7F + 0xDF, 0xF5, 0x24, 0xA9, 0x3E, 0xA8, 0x43, 0xC9, // 80..87 + 0xD7, 0x79, 0xD6, 0xF6, 0x7C, 0x22, 0xB9, 0x03, // 88..8F + 0xE0, 0x0F, 0xEC, 0xDE, 0x7A, 0x94, 0xB0, 0xBC, // 90..97 + 0xDC, 0xE8, 0x28, 0x50, 0x4E, 0x33, 0x0A, 0x4A, // 98..9F + 0xA7, 0x97, 0x60, 0x73, 0x1E, 0x00, 0x62, 0x44, // A0..A7 + 0x1A, 0xB8, 0x38, 0x82, 0x64, 0x9F, 0x26, 0x41, // A8..AF + 0xAD, 0x45, 0x46, 0x92, 0x27, 0x5E, 0x55, 0x2F, // B0..B7 + 0x8C, 0xA3, 0xA5, 0x7D, 0x69, 0xD5, 0x95, 0x3B, // B8..BF + 0x07, 0x58, 0xB3, 0x40, 0x86, 0xAC, 0x1D, 0xF7, // C0..C7 + 0x30, 0x37, 0x6B, 0xE4, 0x88, 0xD9, 0xE7, 0x89, // C8..CF + 0xE1, 0x1B, 0x83, 0x49, 0x4C, 0x3F, 0xF8, 0xFE, // D0..D7 + 0x8D, 0x53, 0xAA, 0x90, 0xCA, 0xD8, 0x85, 0x61, // D8..DF + 0x20, 0x71, 0x67, 0xA4, 0x2D, 0x2B, 0x09, 0x5B, // E0..E7 + 0xCB, 0x9B, 0x25, 0xD0, 0xBE, 0xE5, 0x6C, 0x52, // E8..EF + 0x59, 0xA6, 0x74, 0xD2, 0xE6, 0xF4, 0xB4, 0xC0, // F0..F7 + 0xD1, 0x66, 0xAF, 0xC2, 0x39, 0x4B, 0x63, 0xB6, // F8..FF +}; + +// Inverse S-Box + +static const uint8_t kuz_pi_inv[0x100] = { + 0xA5, 0x2D, 0x32, 0x8F, 0x0E, 0x30, 0x38, 0xC0, // 00..07 + 0x54, 0xE6, 0x9E, 0x39, 0x55, 0x7E, 0x52, 0x91, // 08..0F + 0x64, 0x03, 0x57, 0x5A, 0x1C, 0x60, 0x07, 0x18, // 10..17 + 0x21, 0x72, 0xA8, 0xD1, 0x29, 0xC6, 0xA4, 0x3F, // 18..1F + 0xE0, 0x27, 0x8D, 0x0C, 0x82, 0xEA, 0xAE, 0xB4, // 20..27 + 0x9A, 0x63, 0x49, 0xE5, 0x42, 0xE4, 0x15, 0xB7, // 28..2F + 0xC8, 0x06, 0x70, 0x9D, 0x41, 0x75, 0x19, 0xC9, // 30..37 + 0xAA, 0xFC, 0x4D, 0xBF, 0x2A, 0x73, 0x84, 0xD5, // 38..3F + 0xC3, 0xAF, 0x2B, 0x86, 0xA7, 0xB1, 0xB2, 0x5B, // 40..47 + 0x46, 0xD3, 0x9F, 0xFD, 0xD4, 0x0F, 0x9C, 0x2F, // 48..4F + 0x9B, 0x43, 0xEF, 0xD9, 0x79, 0xB6, 0x53, 0x7F, // 50..57 + 0xC1, 0xF0, 0x23, 0xE7, 0x25, 0x5E, 0xB5, 0x1E, // 58..5F + 0xA2, 0xDF, 0xA6, 0xFE, 0xAC, 0x22, 0xF9, 0xE2, // 60..67 + 0x4A, 0xBC, 0x35, 0xCA, 0xEE, 0x78, 0x05, 0x6B, // 68..6F + 0x51, 0xE1, 0x59, 0xA3, 0xF2, 0x71, 0x56, 0x11, // 70..77 + 0x6A, 0x89, 0x94, 0x65, 0x8C, 0xBB, 0x77, 0x3C, // 78..7F + 0x7B, 0x28, 0xAB, 0xD2, 0x31, 0xDE, 0xC4, 0x5F, // 80..87 + 0xCC, 0xCF, 0x76, 0x2C, 0xB8, 0xD8, 0x2E, 0x36, // 88..8F + 0xDB, 0x69, 0xB3, 0x14, 0x95, 0xBE, 0x62, 0xA1, // 90..97 + 0x3B, 0x16, 0x66, 0xE9, 0x5C, 0x6C, 0x6D, 0xAD, // 98..9F + 0x37, 0x61, 0x4B, 0xB9, 0xE3, 0xBA, 0xF1, 0xA0, // A0..A7 + 0x85, 0x83, 0xDA, 0x47, 0xC5, 0xB0, 0x33, 0xFA, // A8..AF + 0x96, 0x6F, 0x6E, 0xC2, 0xF6, 0x50, 0xFF, 0x5D, // B0..B7 + 0xA9, 0x8E, 0x17, 0x1B, 0x97, 0x7D, 0xEC, 0x58, // B8..BF + 0xF7, 0x1F, 0xFB, 0x7C, 0x09, 0x0D, 0x7A, 0x67, // C0..C7 + 0x45, 0x87, 0xDC, 0xE8, 0x4F, 0x1D, 0x4E, 0x04, // C8..CF + 0xEB, 0xF8, 0xF3, 0x3E, 0x3D, 0xBD, 0x8A, 0x88, // D0..D7 + 0xDD, 0xCD, 0x0B, 0x13, 0x98, 0x02, 0x93, 0x80, // D8..DF + 0x90, 0xD0, 0x24, 0x34, 0xCB, 0xED, 0xF4, 0xCE, // E0..E7 + 0x99, 0x10, 0x44, 0x40, 0x92, 0x3A, 0x01, 0x26, // E8..EF + 0x12, 0x1A, 0x48, 0x68, 0xF5, 0x81, 0x8B, 0xC7, // F0..F7 + 0xD6, 0x20, 0x0A, 0x08, 0x00, 0x4C, 0xD7, 0x74 // F8..FF +}; + +// Linear vector from sect 5.1.2 + +static const uint8_t kuz_lvec[16] = { + 0x94, 0x20, 0x85, 0x10, 0xC2, 0xC0, 0x01, 0xFB, + 0x01, 0xC0, 0xC2, 0x10, 0x85, 0x20, 0x94, 0x01 +}; + +//Common interface for encryption algorithms +const CipherAlgo kuznyechikCipherAlgo = +{ + "Kuznyechik", + sizeof(KuznyechikContext), + CIPHER_ALGO_TYPE_BLOCK, + KUZNYECHIK_BLOCK_SIZE, + (CipherAlgoInit)kuznyechikInit, + NULL, + NULL, + (CipherAlgoEncryptBlock)kuznyechikEncryptBlock, + (CipherAlgoDecryptBlock)kuznyechikDecryptBlock, + (CipherAlgoDeinit)kuznyechikDeinit +}; + +// poly multiplication mod p(x) = x^8 + x^7 + x^6 + x + 1 +// totally not constant time + +static uint8_t kuz_mul_gf256(uint8_t x, uint8_t y) +{ +/* uint8_t z = 0; + + while( y ) { + z ^= x * (y & 1); + x = (x << 1) ^ (0xC3 * (x >> 7)); + y >>= 1; + } + return z; +*/ + uint8_t z; + + z = 0; + while (y) { + if (y & 1) + z ^= x; + x = (x << 1) ^ (x & 0x80 ? 0xC3 : 0x00); + y >>= 1; + } + return z; +} + +// linear operation l + +static void kuz_l(w128_t *w) +{ + int i, j; + uint8_t x; + + // 16 rounds + for (j = 0; j < 16; j++) { + + // An LFSR with 16 elements from GF(2^8) + x = w->b[15]; // since lvec[15] = 1 + + for (i = 14; i >= 0; i--) { + w->b[i + 1] = w->b[i]; + x ^= kuz_mul_gf256(w->b[i], kuz_lvec[i]); + } + w->b[0] = x; + } +} + +// inverse of linear operation l + +static void kuz_l_inv(w128_t *w) +{ + int i, j; + uint8_t x; + + // 16 rounds + for (j = 0; j < 16; j++) { + + x = w->b[0]; + for (i = 0; i < 15; i++) { + w->b[i] = w->b[i + 1]; + x ^= kuz_mul_gf256(w->b[i], kuz_lvec[i]); + } + w->b[15] = x; + } +} + +/* +//AES128-ECB OID (2.16.840.1.101.3.4.1.1) +const uint8_t AES128_ECB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x01}; +//AES128-CBC OID (2.16.840.1.101.3.4.1.2) +const uint8_t AES128_CBC_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02}; +//AES128-OFB OID (2.16.840.1.101.3.4.1.3) +const uint8_t AES128_OFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x03}; +//AES128-CFB OID (2.16.840.1.101.3.4.1.4) +const uint8_t AES128_CFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x04}; +//AES128-GCM OID (2.16.840.1.101.3.4.1.6) +const uint8_t AES128_GCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x06}; +//AES128-CCM OID (2.16.840.1.101.3.4.1.7) +const uint8_t AES128_CCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x07}; + +//AES192-ECB OID (2.16.840.1.101.3.4.1.21) +const uint8_t AES192_ECB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x15}; +//AES192-CBC OID (2.16.840.1.101.3.4.1.22) +const uint8_t AES192_CBC_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16}; +//AES192-OFB OID (2.16.840.1.101.3.4.1.23) +const uint8_t AES192_OFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x17}; +//AES192-CFB OID (2.16.840.1.101.3.4.1.24) +const uint8_t AES192_CFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x18}; +//AES192-GCM OID (2.16.840.1.101.3.4.1.26) +const uint8_t AES192_GCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x1A}; +//AES192-CCM OID (2.16.840.1.101.3.4.1.27) +const uint8_t AES192_CCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x1B}; + +//AES256-ECB OID (2.16.840.1.101.3.4.1.41) +const uint8_t AES256_ECB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x29}; +//AES256-CBC OID (2.16.840.1.101.3.4.1.42) +const uint8_t AES256_CBC_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2A}; +//AES256-OFB OID (2.16.840.1.101.3.4.1.43) +const uint8_t AES256_OFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2B}; +//AES256-CFB OID (2.16.840.1.101.3.4.1.44) +const uint8_t AES256_CFB_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2C}; +//AES256-GCM OID (2.16.840.1.101.3.4.1.46) +const uint8_t AES256_GCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2E}; +//AES256-CCM OID (2.16.840.1.101.3.4.1.47) +const uint8_t AES256_CCM_OID[9] = {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2F}; +*/ + + +/** + * @brief Key expansion + * @param[in] context Pointer to the KUZNYECHIK context to initialize + * @param[in] key Pointer to the key + * @param[in] keyLen Length of the key + * @return Error code + **/ + +__weak_func error_t kuznyechikInit(KuznyechikContext *context, const uint8_t *key, size_t keyLen) +{ + int i, j; + w128_t c, x, y, z; + + //Check parameters + if(context == NULL || key == NULL) + return ERROR_INVALID_PARAMETER; + + //Check the length of the key + if(keyLen != 16) + //Report an error + return ERROR_INVALID_KEY_LENGTH; + + for (i = 0; i < 16; i++) { + // this will be have to changed for little-endian systems + x.b[i] = key[i]; + y.b[i] = key[i + 16]; + } + + context->ek[0].q[0] = x.q[0]; + context->ek[0].q[1] = x.q[1]; + context->ek[1].q[0] = y.q[0]; + context->ek[1].q[1] = y.q[1]; + + for (i = 1; i <= 32; i++) { + + // C Value + c.q[0] = 0; + c.q[1] = 0; + c.b[15] = i; // load round in lsb + kuz_l(&c); + + z.q[0] = x.q[0] ^ c.q[0]; + z.q[1] = x.q[1] ^ c.q[1]; + for (j = 0; j < 16; j++) + z.b[j] = kuz_pi[z.b[j]]; + kuz_l(&z); + z.q[0] ^= y.q[0]; + z.q[1] ^= y.q[1]; + + y.q[0] = x.q[0]; + y.q[1] = x.q[1]; + + x.q[0] = z.q[0]; + x.q[1] = z.q[1]; + + if ((i & 7) == 0) { + context->ek[(i >> 2)].q[0] = x.q[0]; + context->ek[(i >> 2)].q[1] = x.q[1]; + context->ek[(i >> 2) + 1].q[0] = y.q[0]; + context->ek[(i >> 2) + 1].q[1] = y.q[1]; + } + } + for (i = 0; i < 10; i++) + context->dk[i] = context->ek[i]; + //No error to report + return NO_ERROR; +} + + +/** + * @brief Encrypt a 16-byte block using KUZNYECHIK algorithm + * @param[in] context Pointer to the KUZNYECHIK context + * @param[in] input Plaintext block to encrypt + * @param[out] output Ciphertext block resulting from encryption + **/ + +void kuznyechikEncryptBlock(KuznyechikContext *context, const uint8_t *input, uint8_t *output) +{ + int i, j; + w128_t x; + + x.q[0] = ((uint64_t *)input)[0]; + x.q[1] = ((uint64_t *)input)[1]; + + for (i = 0; i < 9; i++) { + + x.q[0] ^= context->ek[i].q[0]; + x.q[1] ^= context->ek[i].q[1]; + + for (j = 0; j < 16; j++) + x.b[j] = kuz_pi[x.b[j]]; + kuz_l(&x); + } + ((uint64_t *)output)[0] = x.q[0] ^ context->ek[9].q[0]; + ((uint64_t *)output)[1] = x.q[1] ^ context->ek[9].q[1]; +} + + +/** + * @brief Decypt a 16-byte block using KUZNYECHIK algorithm + * @param[in] context Pointer to the KUZNYECHIK context + * @param[in] input Plaintext block to encrypt + * @param[out] output Ciphertext block resulting from encryption + **/ + +void kuznyechikDecryptBlock(KuznyechikContext *context, const uint8_t *input, uint8_t *output) +{ + int i, j; + w128_t x; + + x.q[0] = ((uint64_t *)input)[0] ^ context->dk[9].q[0]; + x.q[1] = ((uint64_t *)input)[1] ^ context->dk[9].q[1]; + + for (i = 8; i >= 0; i--) { + + kuz_l_inv(&x); + for (j = 0; j < 16; j++) + x.b[j] = kuz_pi_inv[x.b[j]]; + + x.q[0] ^= context->dk[i].q[0]; + x.q[1] ^= context->dk[i].q[1]; + } + ((uint64_t *)output)[0] = x.q[0]; + ((uint64_t *)output)[1] = x.q[1]; +} + + +/** + * @brief Release KUZNYECHIK context + * @param[in] context Pointer to the KUZNYECHIK context + **/ + +__weak_func void kuznyechikDeinit(KuznyechikContext *context) +{ + //Clear KUZNYECHIK context + osMemset(context, 0, sizeof(KuznyechikContext)); +} + +#endif From bb254ee1e733740579aec3a1f53a8b90aac603e2 Mon Sep 17 00:00:00 2001 From: Valerii Novikov <43934124+novval@users.noreply.github.com> Date: Tue, 9 Jul 2024 16:17:44 +0500 Subject: [PATCH 8/8] Update README.md --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index c9f54531..78644fa4 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,2 @@ # CycloneCrypto Cryptographic Library - -Create the directory structure as shown below: -.. -common -- repository contents https://github.com/novval/Common -cyclone_crypto -- repository contents https://github.com/novval/CycloneCRYPTO -demo -- repository contents https://github.com/novval/cyclone_demo