From gniibe at fsij.org Thu Apr 1 10:07:44 2021 From: gniibe at fsij.org (NIIBE Yutaka) Date: Thu, 01 Apr 2021 17:07:44 +0900 Subject: CMAC + SERPENT/IDEA/RC2 buffer overflow/crash with oversized key In-Reply-To: References: Message-ID: <878s624ecv.fsf@iwagami.gniibe.org> Hello, Thank you for your report. Guido Vranken via Gcrypt-devel wrote: > I think the correct approach is to > make gcry_mac_setkey() return an error code if the key has an inappropriate > size. Something like this? -- diff --git a/cipher/idea.c b/cipher/idea.c index 0a810818..7f706660 100644 --- a/cipher/idea.c +++ b/cipher/idea.c @@ -251,7 +251,9 @@ do_setkey( IDEA_context *c, const byte *key, unsigned int keylen ) if( selftest_failed ) return GPG_ERR_SELFTEST_FAILED; - assert(keylen == 16); + if (keylen != 16) + return GPG_ERR_INV_KEYLEN; + c->have_dk = 0; expand_key( key, c->ek ); invert_key( c->ek, c->dk ); diff --git a/cipher/rfc2268.c b/cipher/rfc2268.c index f018b640..b093f022 100644 --- a/cipher/rfc2268.c +++ b/cipher/rfc2268.c @@ -228,6 +228,9 @@ setkey_core (void *context, const unsigned char *key, unsigned int keylen, int w if (keylen < 40 / 8) /* We want at least 40 bits. */ return GPG_ERR_INV_KEYLEN; + if (keylen > 128) + return GPG_ERR_INV_KEYLEN; + S = (unsigned char *) ctx->S; for (i = 0; i < keylen; i++) diff --git a/cipher/serpent.c b/cipher/serpent.c index 3c5eed2c..d2f7f16e 100644 --- a/cipher/serpent.c +++ b/cipher/serpent.c @@ -732,12 +732,15 @@ serpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys) } /* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */ -static void +static gcry_err_code_t serpent_setkey_internal (serpent_context_t *context, const byte *key, unsigned int key_length) { serpent_key_t key_prepared; + if (key_length > 32) + return GPG_ERR_INV_KEYLEN; + serpent_key_prepare (key, key_length, key_prepared); serpent_subkeys_generate (key_prepared, context->keys); @@ -758,6 +761,7 @@ serpent_setkey_internal (serpent_context_t *context, #endif wipememory (key_prepared, sizeof(key_prepared)); + return 0; } /* Initialize CTX with the key KEY of KEY_LENGTH bytes. */ @@ -791,7 +795,7 @@ serpent_setkey (void *ctx, if (serpent_test_ret) ret = GPG_ERR_SELFTEST_FAILED; else - serpent_setkey_internal (context, key, key_length); + ret = serpent_setkey_internal (context, key, key_length); return ret; } From gniibe at fsij.org Fri Apr 2 03:17:12 2021 From: gniibe at fsij.org (NIIBE Yutaka) Date: Fri, 02 Apr 2021 10:17:12 +0900 Subject: CMAC + SERPENT/IDEA/RC2 buffer overflow/crash with oversized key In-Reply-To: <878s624ecv.fsf@iwagami.gniibe.org> References: <878s624ecv.fsf@iwagami.gniibe.org> Message-ID: <87tuopwkmf.fsf@iwagami.gniibe.org> NIIBE Yutaka wrote: > Something like this? After I confirmed it works correctly (returns an error), I applied and pushed to libgcrypt master. -- From ametzler at bebt.de Fri Apr 2 18:00:02 2021 From: ametzler at bebt.de (Andreas Metzler) Date: Fri, 2 Apr 2021 18:00:02 +0200 Subject: CMAC + SERPENT/IDEA/RC2 buffer overflow/crash with oversized key In-Reply-To: References: Message-ID: On 2021-03-31 Guido Vranken via Gcrypt-devel wrote: > In the program below, each of three calls to cmac() causes a different > crash (use AddressSanitizer to be sure). I think the correct approach is to > make gcry_mac_setkey() return an error code if the key has an inappropriate > size. [...] Is this exploitable? cu Andreas -- `What a good friend you are to him, Dr. Maturin. His other friends are so grateful to you.' `I sew his ears on from time to time, sure' From guidovranken at gmail.com Fri Apr 2 22:51:29 2021 From: guidovranken at gmail.com (Guido Vranken) Date: Fri, 2 Apr 2021 22:51:29 +0200 Subject: CMAC + SERPENT/IDEA/RC2 buffer overflow/crash with oversized key In-Reply-To: References: Message-ID: In the case of IDEA, an oversized key only appears to cause a crash (assertion failure, so no memory corruption). In the case of SERPENT, it appears to overwrite a stack buffer. That makes it unlikely to be exploitable when stack protector is enabled (which is the case for the binaries of most Linux distro's I think). In the case of RC2, it appears to overwrite a heap buffer. That makes it more likely to be exploitable but you probably still have to deal with ASLR. In addition to that the host application needs to allow setting oversized keys but applications usually only allow hardcoded, legal key lengths. With that said, exploitation might be possible in specific circumstances. On Fri, Apr 2, 2021 at 6:00 PM Andreas Metzler wrote: > On 2021-03-31 Guido Vranken via Gcrypt-devel > wrote: > > In the program below, each of three calls to cmac() causes a different > > crash (use AddressSanitizer to be sure). I think the correct approach is > to > > make gcry_mac_setkey() return an error code if the key has an > inappropriate > > size. > [...] > > Is this exploitable? > > cu Andreas > -- > `What a good friend you are to him, Dr. Maturin. His other friends are > so grateful to you.' > `I sew his ears on from time to time, sure' > > _______________________________________________ > Gcrypt-devel mailing list > Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From wk at gnupg.org Sun Apr 4 19:15:01 2021 From: wk at gnupg.org (Werner Koch) Date: Sun, 04 Apr 2021 19:15:01 +0200 Subject: CMAC + SERPENT/IDEA/RC2 buffer overflow/crash with oversized key In-Reply-To: (Guido Vranken via Gcrypt-devel's message of "Fri, 2 Apr 2021 22:51:29 +0200") References: Message-ID: <87eefqc6p6.fsf@wheatstone.g10code.de> On Fri, 2 Apr 2021 22:51, Guido Vranken said: > With that said, exploitation might be possible in specific circumstances. ... and it would be much easier to attack the application than Libgcrypt. An application which does not take care from where it gets the key has for sure a lot of other problems. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 227 bytes Desc: not available URL: From jussi.kivilinna at iki.fi Fri Apr 9 18:53:12 2021 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 9 Apr 2021 19:53:12 +0300 Subject: [PATCH 1/3] md: remove hash_buffer function from algorithms Message-ID: <20210409165314.1532424-1-jussi.kivilinna@iki.fi> * cipher/md.c (_gcry_md_hash_buffer): Remove used of 'spec->hash_buffer'. * cipher/blake2.c (DEFINE_BLAKE2_VARIANT): Remove *_hash_buffer. * cipher/crc.c: Remove spec hash_buffer NULL pointers. * cipher/gostr3411-94.c: Remove spec hash_buffer NULL pointers. * cipher/keccak.c (_gcry_sha3_hash_buffer (_gcry_sha3_224_hash_buffer, _gcry_sha3_256_hash_buffer): Remove. (_gcry_sha3_384_hash_buffer, _gcry_sha3_512_hash_buffer): Remove. * cipher/md2.c: Remove spec hash_buffer NULL pointers. * cipher/md4.c: Remove spec hash_buffer NULL pointers. * cipher/md5.c: Remove spec hash_buffer NULL pointers. * cipher/rmd160.c (_gcry_rmd160_hash_buffer): Remove. * cipher/sha1.c (_gcry_sha1_hash_buffer): Rewrite using _gcry_sha1_hash_buffers. (_gcry_sha1_hash_buffers): Make static. (_gcry_digest_spec_sha1): Remove hash_buffer pointer. * cipher/sha256.c (_gcry_sha256_hash_buffer) (_gcry_sha224_hash_buffer): Remove. (_gcry_sha256_hash_buffers): Make static. * cipher/sha512.c (_gcry_sha512_hash_buffer) (_gcry_sha384_hash_buffer, _gcry_sha512_256_hash_buffer) (_gcry_sha512_224_hash_buffer): Remove. (_gcry_sha512_hash_buffers): Make static. * cipher/sm3.c (_gcry_sm3_hash_buffer): Remove. (_gcry_sm3_hash_buffers): Make static. * cipher/stribog.c: Remove spec hash_buffer NULL pointers. * cipher/tiger.c: Remove spec hash_buffer NULL pointers. * cipher/whirlpool.c: Remove spec hash_buffer NULL pointers. * src/cipher-proto.h (gcry_md_hash_buffer_t): Remove. (gcry_md_spec_t): Remove 'hash_buffer'. * src/cipher.h (_gcry_rmd160_hash_buffer, _gcry_sha1_hash_buffers) (_gcry_sha256_hash_buffer, _gcry_sha256_hash_buffers) (_gcry_sha512_hash_buffer, _gcry_sha512_hash_buffers) (_gcry_sm3_hash_buffer, _gcry_sm3_hash_buffers): Remove. -- Patch removes hash_buffer functions and uses hash_buffers instead for code deduplication. Signed-off-by: Jussi Kivilinna --- cipher/blake2.c | 11 ------- cipher/crc.c | 6 ++-- cipher/gostr3411-94.c | 4 +-- cipher/keccak.c | 51 ++++--------------------------- cipher/md.c | 6 +--- cipher/md2.c | 2 +- cipher/md4.c | 2 +- cipher/md5.c | 2 +- cipher/rmd160.c | 16 ++-------- cipher/sha1.c | 30 +++++++++--------- cipher/sha256.c | 36 +++------------------- cipher/sha512.c | 71 ++++++------------------------------------- cipher/sm3.c | 19 ++---------- cipher/stribog.c | 4 +-- cipher/tiger.c | 6 ++-- cipher/whirlpool.c | 2 +- src/cipher-proto.h | 5 --- src/cipher.h | 24 --------------- 18 files changed, 56 insertions(+), 241 deletions(-) diff --git a/cipher/blake2.c b/cipher/blake2.c index f2bf49e5..0243ed33 100644 --- a/cipher/blake2.c +++ b/cipher/blake2.c @@ -946,16 +946,6 @@ gcry_err_code_t _gcry_blake2_init_with_key(void *ctx, unsigned int flags, gcry_assert (err == 0); \ } \ static void \ - _gcry_blake2##bs##_##dbits##_hash_buffer(void *outbuf, \ - const void *buffer, size_t length) \ - { \ - BLAKE2##BS##_CONTEXT hd; \ - blake2##bs##_##dbits##_init (&hd, 0); \ - blake2##bs##_write (&hd, buffer, length); \ - blake2##bs##_final (&hd); \ - memcpy (outbuf, blake2##bs##_read (&hd), dbits / 8); \ - } \ - static void \ _gcry_blake2##bs##_##dbits##_hash_buffers(void *outbuf, \ const gcry_buffer_t *iov, int iovcnt) \ { \ @@ -980,7 +970,6 @@ gcry_err_code_t _gcry_blake2_init_with_key(void *ctx, unsigned int flags, DIM (blake2##bs##_##dbits##_asn), oid_spec_blake2##bs##_##dbits, \ dbits / 8, blake2##bs##_##dbits##_init, blake2##bs##_write, \ blake2##bs##_final, blake2##bs##_read, NULL, \ - _gcry_blake2##bs##_##dbits##_hash_buffer, \ _gcry_blake2##bs##_##dbits##_hash_buffers, \ sizeof (BLAKE2##BS##_CONTEXT), selftests_blake2##bs \ }; diff --git a/cipher/crc.c b/cipher/crc.c index 6d70f644..db8d8dc9 100644 --- a/cipher/crc.c +++ b/cipher/crc.c @@ -932,7 +932,7 @@ gcry_md_spec_t _gcry_digest_spec_crc32 = GCRY_MD_CRC32, {0, 1}, "CRC32", NULL, 0, NULL, 4, crc32_init, crc32_write, crc32_final, crc32_read, NULL, - NULL, NULL, + NULL, sizeof (CRC_CONTEXT) }; @@ -941,7 +941,7 @@ gcry_md_spec_t _gcry_digest_spec_crc32_rfc1510 = GCRY_MD_CRC32_RFC1510, {0, 1}, "CRC32RFC1510", NULL, 0, NULL, 4, crc32rfc1510_init, crc32_write, crc32rfc1510_final, crc32_read, NULL, - NULL, NULL, + NULL, sizeof (CRC_CONTEXT) }; @@ -950,6 +950,6 @@ gcry_md_spec_t _gcry_digest_spec_crc24_rfc2440 = GCRY_MD_CRC24_RFC2440, {0, 1}, "CRC24RFC2440", NULL, 0, NULL, 3, crc24rfc2440_init, crc24rfc2440_write, crc24rfc2440_final, crc32_read, NULL, - NULL, NULL, + NULL, sizeof (CRC_CONTEXT) }; diff --git a/cipher/gostr3411-94.c b/cipher/gostr3411-94.c index 7cf0637e..588d5dc1 100644 --- a/cipher/gostr3411-94.c +++ b/cipher/gostr3411-94.c @@ -370,7 +370,7 @@ gcry_md_spec_t _gcry_digest_spec_gost3411_94 = GCRY_MD_GOSTR3411_94, {0, 0}, "GOSTR3411_94", NULL, 0, NULL, 32, gost3411_init, _gcry_md_block_write, gost3411_final, gost3411_read, NULL, - NULL, NULL, + NULL, sizeof (GOSTR3411_CONTEXT) }; gcry_md_spec_t _gcry_digest_spec_gost3411_cp = @@ -378,6 +378,6 @@ gcry_md_spec_t _gcry_digest_spec_gost3411_cp = GCRY_MD_GOSTR3411_CP, {0, 0}, "GOSTR3411_CP", asn, DIM (asn), oid_spec_gostr3411, 32, gost3411_cp_init, _gcry_md_block_write, gost3411_final, gost3411_read, NULL, - NULL, NULL, + NULL, sizeof (GOSTR3411_CONTEXT) }; diff --git a/cipher/keccak.c b/cipher/keccak.c index 795a02e5..bb643e3d 100644 --- a/cipher/keccak.c +++ b/cipher/keccak.c @@ -1221,21 +1221,6 @@ keccak_extract (void *context, void *out, size_t outlen) } -/* Shortcut functions which puts the hash value of the supplied buffer - * into outbuf which must have a size of 'spec->mdlen' bytes. */ -static void -_gcry_sha3_hash_buffer (void *outbuf, const void *buffer, size_t length, - const gcry_md_spec_t *spec) -{ - KECCAK_CONTEXT hd; - - spec->init (&hd, 0); - keccak_write (&hd, buffer, length); - keccak_final (&hd); - memcpy (outbuf, keccak_read (&hd), spec->mdlen); -} - - /* Variant of the above shortcut function using multiple buffers. */ static void _gcry_sha3_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt, @@ -1251,30 +1236,6 @@ _gcry_sha3_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt, } -static void -_gcry_sha3_224_hash_buffer (void *outbuf, const void *buffer, size_t length) -{ - _gcry_sha3_hash_buffer (outbuf, buffer, length, &_gcry_digest_spec_sha3_224); -} - -static void -_gcry_sha3_256_hash_buffer (void *outbuf, const void *buffer, size_t length) -{ - _gcry_sha3_hash_buffer (outbuf, buffer, length, &_gcry_digest_spec_sha3_256); -} - -static void -_gcry_sha3_384_hash_buffer (void *outbuf, const void *buffer, size_t length) -{ - _gcry_sha3_hash_buffer (outbuf, buffer, length, &_gcry_digest_spec_sha3_384); -} - -static void -_gcry_sha3_512_hash_buffer (void *outbuf, const void *buffer, size_t length) -{ - _gcry_sha3_hash_buffer (outbuf, buffer, length, &_gcry_digest_spec_sha3_512); -} - static void _gcry_sha3_224_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) @@ -1526,7 +1487,7 @@ gcry_md_spec_t _gcry_digest_spec_sha3_224 = GCRY_MD_SHA3_224, {0, 1}, "SHA3-224", sha3_224_asn, DIM (sha3_224_asn), oid_spec_sha3_224, 28, sha3_224_init, keccak_write, keccak_final, keccak_read, NULL, - _gcry_sha3_224_hash_buffer, _gcry_sha3_224_hash_buffers, + _gcry_sha3_224_hash_buffers, sizeof (KECCAK_CONTEXT), run_selftests }; @@ -1535,7 +1496,7 @@ gcry_md_spec_t _gcry_digest_spec_sha3_256 = GCRY_MD_SHA3_256, {0, 1}, "SHA3-256", sha3_256_asn, DIM (sha3_256_asn), oid_spec_sha3_256, 32, sha3_256_init, keccak_write, keccak_final, keccak_read, NULL, - _gcry_sha3_256_hash_buffer, _gcry_sha3_256_hash_buffers, + _gcry_sha3_256_hash_buffers, sizeof (KECCAK_CONTEXT), run_selftests }; @@ -1544,7 +1505,7 @@ gcry_md_spec_t _gcry_digest_spec_sha3_384 = GCRY_MD_SHA3_384, {0, 1}, "SHA3-384", sha3_384_asn, DIM (sha3_384_asn), oid_spec_sha3_384, 48, sha3_384_init, keccak_write, keccak_final, keccak_read, NULL, - _gcry_sha3_384_hash_buffer, _gcry_sha3_384_hash_buffers, + _gcry_sha3_384_hash_buffers, sizeof (KECCAK_CONTEXT), run_selftests }; @@ -1553,7 +1514,7 @@ gcry_md_spec_t _gcry_digest_spec_sha3_512 = GCRY_MD_SHA3_512, {0, 1}, "SHA3-512", sha3_512_asn, DIM (sha3_512_asn), oid_spec_sha3_512, 64, sha3_512_init, keccak_write, keccak_final, keccak_read, NULL, - _gcry_sha3_512_hash_buffer, _gcry_sha3_512_hash_buffers, + _gcry_sha3_512_hash_buffers, sizeof (KECCAK_CONTEXT), run_selftests }; @@ -1562,7 +1523,7 @@ gcry_md_spec_t _gcry_digest_spec_shake128 = GCRY_MD_SHAKE128, {0, 1}, "SHAKE128", shake128_asn, DIM (shake128_asn), oid_spec_shake128, 0, shake128_init, keccak_write, keccak_final, NULL, keccak_extract, - NULL, NULL, + NULL, sizeof (KECCAK_CONTEXT), run_selftests }; @@ -1571,7 +1532,7 @@ gcry_md_spec_t _gcry_digest_spec_shake256 = GCRY_MD_SHAKE256, {0, 1}, "SHAKE256", shake256_asn, DIM (shake256_asn), oid_spec_shake256, 0, shake256_init, keccak_write, keccak_final, NULL, keccak_extract, - NULL, NULL, + NULL, sizeof (KECCAK_CONTEXT), run_selftests }; diff --git a/cipher/md.c b/cipher/md.c index 87979059..f142e9c3 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -1205,11 +1205,7 @@ _gcry_md_hash_buffer (int algo, void *digest, } } - if (spec->hash_buffer != NULL) - { - spec->hash_buffer (digest, buffer, length); - } - else if (spec->hash_buffers != NULL) + if (spec->hash_buffers != NULL) { gcry_buffer_t iov; diff --git a/cipher/md2.c b/cipher/md2.c index dc4deac3..8fc5a6da 100644 --- a/cipher/md2.c +++ b/cipher/md2.c @@ -176,6 +176,6 @@ gcry_md_spec_t _gcry_digest_spec_md2 = GCRY_MD_MD2, {0, 0}, "MD2", asn, DIM (asn), oid_spec_md2, 16, md2_init, _gcry_md_block_write, md2_final, md2_read, NULL, - NULL, NULL, + NULL, sizeof (MD2_CONTEXT) }; diff --git a/cipher/md4.c b/cipher/md4.c index b55443a8..46aa8681 100644 --- a/cipher/md4.c +++ b/cipher/md4.c @@ -291,6 +291,6 @@ gcry_md_spec_t _gcry_digest_spec_md4 = GCRY_MD_MD4, {0, 0}, "MD4", asn, DIM (asn), oid_spec_md4,16, md4_init, _gcry_md_block_write, md4_final, md4_read, NULL, - NULL, NULL, + NULL, sizeof (MD4_CONTEXT) }; diff --git a/cipher/md5.c b/cipher/md5.c index 32cb535a..e98aea52 100644 --- a/cipher/md5.c +++ b/cipher/md5.c @@ -317,6 +317,6 @@ gcry_md_spec_t _gcry_digest_spec_md5 = GCRY_MD_MD5, {0, 0}, "MD5", asn, DIM (asn), oid_spec_md5, 16, md5_init, _gcry_md_block_write, md5_final, md5_read, NULL, - NULL, NULL, + NULL, sizeof (MD5_CONTEXT) }; diff --git a/cipher/rmd160.c b/cipher/rmd160.c index e12ff017..37462130 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -477,21 +477,9 @@ rmd160_read( void *context ) /**************** - * Shortcut functions which puts the hash value of the supplied buffer + * Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 20 bytes. */ -void -_gcry_rmd160_hash_buffer (void *outbuf, const void *buffer, size_t length ) -{ - RMD160_CONTEXT hd; - - rmd160_init (&hd, 0); - _gcry_md_block_write ( &hd, buffer, length ); - rmd160_final ( &hd ); - memcpy ( outbuf, hd.bctx.buf, 20 ); -} - -/* Variant of the above shortcut function using a multiple buffers. */ static void _gcry_rmd160_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) { @@ -524,6 +512,6 @@ gcry_md_spec_t _gcry_digest_spec_rmd160 = GCRY_MD_RMD160, {0, 0}, "RIPEMD160", asn, DIM (asn), oid_spec_rmd160, 20, rmd160_init, _gcry_md_block_write, rmd160_final, rmd160_read, NULL, - _gcry_rmd160_hash_buffer, _gcry_rmd160_hash_buffers, + _gcry_rmd160_hash_buffers, sizeof (RMD160_CONTEXT) }; diff --git a/cipher/sha1.c b/cipher/sha1.c index 35f7376c..48fdbb33 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -631,34 +631,34 @@ sha1_read( void *context ) return hd->bctx.buf; } + /**************** - * Shortcut functions which puts the hash value of the supplied buffer + * Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 20 bytes. */ -void -_gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length) +static void +_gcry_sha1_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) { SHA1_CONTEXT hd; sha1_init (&hd, 0); - _gcry_md_block_write (&hd, buffer, length); + for (;iovcnt > 0; iov++, iovcnt--) + _gcry_md_block_write (&hd, + (const char*)iov[0].data + iov[0].off, iov[0].len); sha1_final (&hd); memcpy (outbuf, hd.bctx.buf, 20); } - -/* Variant of the above shortcut function using a multiple buffers. */ +/* Variant of the above shortcut function using a single buffer. */ void -_gcry_sha1_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) +_gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length) { - SHA1_CONTEXT hd; + gcry_buffer_t iov = { 0 }; - sha1_init (&hd, 0); - for (;iovcnt > 0; iov++, iovcnt--) - _gcry_md_block_write (&hd, - (const char*)iov[0].data + iov[0].off, iov[0].len); - sha1_final (&hd); - memcpy (outbuf, hd.bctx.buf, 20); + iov.data = (void *)buffer; + iov.len = length; + + _gcry_sha1_hash_buffers (outbuf, &iov, 1); } @@ -759,7 +759,7 @@ gcry_md_spec_t _gcry_digest_spec_sha1 = GCRY_MD_SHA1, {0, 1}, "SHA1", asn, DIM (asn), oid_spec_sha1, 20, sha1_init, _gcry_md_block_write, sha1_final, sha1_read, NULL, - _gcry_sha1_hash_buffer, _gcry_sha1_hash_buffers, + _gcry_sha1_hash_buffers, sizeof (SHA1_CONTEXT), run_selftests }; diff --git a/cipher/sha256.c b/cipher/sha256.c index 93505891..871615b6 100644 --- a/cipher/sha256.c +++ b/cipher/sha256.c @@ -628,22 +628,9 @@ sha256_read (void *context) } -/* Shortcut functions which puts the hash value of the supplied buffer +/* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 32 bytes. */ -void -_gcry_sha256_hash_buffer (void *outbuf, const void *buffer, size_t length) -{ - SHA256_CONTEXT hd; - - sha256_init (&hd, 0); - _gcry_md_block_write (&hd, buffer, length); - sha256_final (&hd); - memcpy (outbuf, hd.bctx.buf, 32); -} - - -/* Variant of the above shortcut function using multiple buffers. */ -void +static void _gcry_sha256_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) { SHA256_CONTEXT hd; @@ -657,22 +644,9 @@ _gcry_sha256_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) } -/* Shortcut functions which puts the hash value of the supplied buffer +/* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 28 bytes. */ static void -_gcry_sha224_hash_buffer (void *outbuf, const void *buffer, size_t length) -{ - SHA256_CONTEXT hd; - - sha224_init (&hd, 0); - _gcry_md_block_write (&hd, buffer, length); - sha256_final (&hd); - memcpy (outbuf, hd.bctx.buf, 28); -} - - -/* Variant of the above shortcut function using multiple buffers. */ -static void _gcry_sha224_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) { SHA256_CONTEXT hd; @@ -841,7 +815,7 @@ gcry_md_spec_t _gcry_digest_spec_sha224 = GCRY_MD_SHA224, {0, 1}, "SHA224", asn224, DIM (asn224), oid_spec_sha224, 28, sha224_init, _gcry_md_block_write, sha256_final, sha256_read, NULL, - _gcry_sha224_hash_buffer, _gcry_sha224_hash_buffers, + _gcry_sha224_hash_buffers, sizeof (SHA256_CONTEXT), run_selftests }; @@ -851,7 +825,7 @@ gcry_md_spec_t _gcry_digest_spec_sha256 = GCRY_MD_SHA256, {0, 1}, "SHA256", asn256, DIM (asn256), oid_spec_sha256, 32, sha256_init, _gcry_md_block_write, sha256_final, sha256_read, NULL, - _gcry_sha256_hash_buffer, _gcry_sha256_hash_buffers, + _gcry_sha256_hash_buffers, sizeof (SHA256_CONTEXT), run_selftests }; diff --git a/cipher/sha512.c b/cipher/sha512.c index bc4657a8..a23d5bda 100644 --- a/cipher/sha512.c +++ b/cipher/sha512.c @@ -862,22 +862,9 @@ sha512_read (void *context) } -/* Shortcut functions which puts the hash value of the supplied buffer +/* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 64 bytes. */ -void -_gcry_sha512_hash_buffer (void *outbuf, const void *buffer, size_t length) -{ - SHA512_CONTEXT hd; - - sha512_init (&hd, 0); - _gcry_md_block_write (&hd, buffer, length); - sha512_final (&hd); - memcpy (outbuf, hd.bctx.buf, 64); -} - - -/* Variant of the above shortcut function using multiple buffers. */ -void +static void _gcry_sha512_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) { SHA512_CONTEXT hd; @@ -892,22 +879,9 @@ _gcry_sha512_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) -/* Shortcut functions which puts the hash value of the supplied buffer +/* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 48 bytes. */ static void -_gcry_sha384_hash_buffer (void *outbuf, const void *buffer, size_t length) -{ - SHA512_CONTEXT hd; - - sha384_init (&hd, 0); - _gcry_md_block_write (&hd, buffer, length); - sha512_final (&hd); - memcpy (outbuf, hd.bctx.buf, 48); -} - - -/* Variant of the above shortcut function using multiple buffers. */ -static void _gcry_sha384_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) { SHA512_CONTEXT hd; @@ -922,27 +896,15 @@ _gcry_sha384_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) -/* Shortcut functions which puts the hash value of the supplied buffer +/* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 32 bytes. */ static void -_gcry_sha512_256_hash_buffer (void *outbuf, const void *buffer, size_t length) -{ - SHA512_CONTEXT hd; - - sha512_256_init (&hd, 0); - _gcry_md_block_write (&hd, buffer, length); - sha512_final (&hd); - memcpy (outbuf, hd.bctx.buf, 32); -} - - -/* Variant of the above shortcut function using multiple buffers. */ -static void _gcry_sha512_256_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) { SHA512_CONTEXT hd; + sha512_256_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, @@ -953,22 +915,9 @@ _gcry_sha512_256_hash_buffers (void *outbuf, const gcry_buffer_t *iov, -/* Shortcut functions which puts the hash value of the supplied buffer +/* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 28 bytes. */ static void -_gcry_sha512_224_hash_buffer (void *outbuf, const void *buffer, size_t length) -{ - SHA512_CONTEXT hd; - - sha512_224_init (&hd, 0); - _gcry_md_block_write (&hd, buffer, length); - sha512_final (&hd); - memcpy (outbuf, hd.bctx.buf, 28); -} - - -/* Variant of the above shortcut function using multiple buffers. */ -static void _gcry_sha512_224_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) { @@ -1242,7 +1191,7 @@ gcry_md_spec_t _gcry_digest_spec_sha512 = GCRY_MD_SHA512, {0, 1}, "SHA512", sha512_asn, DIM (sha512_asn), oid_spec_sha512, 64, sha512_init, _gcry_md_block_write, sha512_final, sha512_read, NULL, - _gcry_sha512_hash_buffer, _gcry_sha512_hash_buffers, + _gcry_sha512_hash_buffers, sizeof (SHA512_CONTEXT), run_selftests }; @@ -1272,7 +1221,7 @@ gcry_md_spec_t _gcry_digest_spec_sha384 = GCRY_MD_SHA384, {0, 1}, "SHA384", sha384_asn, DIM (sha384_asn), oid_spec_sha384, 48, sha384_init, _gcry_md_block_write, sha512_final, sha512_read, NULL, - _gcry_sha384_hash_buffer, _gcry_sha384_hash_buffers, + _gcry_sha384_hash_buffers, sizeof (SHA512_CONTEXT), run_selftests }; @@ -1291,7 +1240,7 @@ gcry_md_spec_t _gcry_digest_spec_sha512_256 = GCRY_MD_SHA512_256, {0, 1}, "SHA512_256", sha512_256_asn, DIM (sha512_256_asn), oid_spec_sha512_256, 32, sha512_256_init, _gcry_md_block_write, sha512_final, sha512_read, NULL, - _gcry_sha512_256_hash_buffer, _gcry_sha512_256_hash_buffers, + _gcry_sha512_256_hash_buffers, sizeof (SHA512_CONTEXT), run_selftests }; @@ -1310,7 +1259,7 @@ gcry_md_spec_t _gcry_digest_spec_sha512_224 = GCRY_MD_SHA512_224, {0, 1}, "SHA512_224", sha512_224_asn, DIM (sha512_224_asn), oid_spec_sha512_224, 28, sha512_224_init, _gcry_md_block_write, sha512_final, sha512_read, NULL, - _gcry_sha512_224_hash_buffer, _gcry_sha512_224_hash_buffers, + _gcry_sha512_224_hash_buffers, sizeof (SHA512_CONTEXT), run_selftests }; diff --git a/cipher/sm3.c b/cipher/sm3.c index 0f9bae3b..c687cdf0 100644 --- a/cipher/sm3.c +++ b/cipher/sm3.c @@ -338,22 +338,9 @@ sm3_read (void *context) } -/* Shortcut functions which puts the hash value of the supplied buffer +/* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 32 bytes. */ -void -_gcry_sm3_hash_buffer (void *outbuf, const void *buffer, size_t length) -{ - SM3_CONTEXT hd; - - sm3_init (&hd, 0); - _gcry_md_block_write (&hd, buffer, length); - sm3_final (&hd); - memcpy (outbuf, hd.bctx.buf, 32); -} - - -/* Variant of the above shortcut function using multiple buffers. */ -void +static void _gcry_sm3_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) { SM3_CONTEXT hd; @@ -467,7 +454,7 @@ gcry_md_spec_t _gcry_digest_spec_sm3 = GCRY_MD_SM3, {0, 0}, "SM3", asn_sm3, DIM (asn_sm3), oid_spec_sm3, 32, sm3_init, _gcry_md_block_write, sm3_final, sm3_read, NULL, - _gcry_sm3_hash_buffer, _gcry_sm3_hash_buffers, + _gcry_sm3_hash_buffers, sizeof (SM3_CONTEXT), run_selftests }; diff --git a/cipher/stribog.c b/cipher/stribog.c index f8776a3e..e0ee1515 100644 --- a/cipher/stribog.c +++ b/cipher/stribog.c @@ -1348,7 +1348,7 @@ gcry_md_spec_t _gcry_digest_spec_stribog_256 = GCRY_MD_STRIBOG256, {0, 0}, "STRIBOG256", NULL, 0, oid_spec_stribog256, 32, stribog_init_256, _gcry_md_block_write, stribog_final, stribog_read_256, - NULL, NULL, NULL, + NULL, NULL, sizeof (STRIBOG_CONTEXT) }; @@ -1357,6 +1357,6 @@ gcry_md_spec_t _gcry_digest_spec_stribog_512 = GCRY_MD_STRIBOG512, {0, 0}, "STRIBOG512", NULL, 0, oid_spec_stribog512, 64, stribog_init_512, _gcry_md_block_write, stribog_final, stribog_read_512, - NULL, NULL, NULL, + NULL, NULL, sizeof (STRIBOG_CONTEXT) }; diff --git a/cipher/tiger.c b/cipher/tiger.c index 4039b22b..f8208ac8 100644 --- a/cipher/tiger.c +++ b/cipher/tiger.c @@ -819,7 +819,7 @@ gcry_md_spec_t _gcry_digest_spec_tiger = GCRY_MD_TIGER, {0, 0}, "TIGER192", NULL, 0, NULL, 24, tiger_init, _gcry_md_block_write, tiger_final, tiger_read, NULL, - NULL, NULL, + NULL, sizeof (TIGER_CONTEXT) }; @@ -843,7 +843,7 @@ gcry_md_spec_t _gcry_digest_spec_tiger1 = GCRY_MD_TIGER1, {0, 0}, "TIGER", asn1, DIM (asn1), oid_spec_tiger1, 24, tiger1_init, _gcry_md_block_write, tiger_final, tiger_read, NULL, - NULL, NULL, + NULL, sizeof (TIGER_CONTEXT) }; @@ -855,6 +855,6 @@ gcry_md_spec_t _gcry_digest_spec_tiger2 = GCRY_MD_TIGER2, {0, 0}, "TIGER2", NULL, 0, NULL, 24, tiger2_init, _gcry_md_block_write, tiger_final, tiger_read, NULL, - NULL, NULL, + NULL, sizeof (TIGER_CONTEXT) }; diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c index 79b2026b..f6e5a7db 100644 --- a/cipher/whirlpool.c +++ b/cipher/whirlpool.c @@ -1530,6 +1530,6 @@ gcry_md_spec_t _gcry_digest_spec_whirlpool = GCRY_MD_WHIRLPOOL, {0, 0}, "WHIRLPOOL", NULL, 0, NULL, 64, whirlpool_init, whirlpool_write, whirlpool_final, whirlpool_read, NULL, - NULL, NULL, + NULL, sizeof (whirlpool_context_t) }; diff --git a/src/cipher-proto.h b/src/cipher-proto.h index f9fbb553..dde56d30 100644 --- a/src/cipher-proto.h +++ b/src/cipher-proto.h @@ -221,10 +221,6 @@ typedef unsigned char *(*gcry_md_read_t) (void *c); /* Type for the md_extract function. */ typedef void (*gcry_md_extract_t) (void *c, void *outbuf, size_t nbytes); -/* Type for the md_hash_buffer function. */ -typedef void (*gcry_md_hash_buffer_t) (void *outbuf, const void *buffer, - size_t length); - /* Type for the md_hash_buffers function. */ typedef void (*gcry_md_hash_buffers_t) (void *outbuf, const gcry_buffer_t *iov, int iovcnt); @@ -252,7 +248,6 @@ typedef struct gcry_md_spec gcry_md_final_t final; gcry_md_read_t read; gcry_md_extract_t extract; - gcry_md_hash_buffer_t hash_buffer; gcry_md_hash_buffers_t hash_buffers; size_t contextsize; /* allocate this amount of context */ selftest_func_t selftest; diff --git a/src/cipher.h b/src/cipher.h index 908e3b78..2efe00fa 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -114,33 +114,9 @@ gcry_err_code_t _gcry_cipher_cmac_check_tag gcry_err_code_t _gcry_cipher_cmac_set_subkeys /* */ (gcry_cipher_hd_t c); -/*-- rmd160.c --*/ -void _gcry_rmd160_hash_buffer (void *outbuf, - const void *buffer, size_t length); - /*-- sha1.c --*/ void _gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length); -void _gcry_sha1_hash_buffers (void *outbuf, - const gcry_buffer_t *iov, int iovcnt); - -/*-- sha256.c --*/ -void _gcry_sha256_hash_buffer (void *outbuf, - const void *buffer, size_t length); -void _gcry_sha256_hash_buffers (void *outbuf, - const gcry_buffer_t *iov, int iovcnt); - -/*-- sha512.c --*/ -void _gcry_sha512_hash_buffer (void *outbuf, - const void *buffer, size_t length); -void _gcry_sha512_hash_buffers (void *outbuf, - const gcry_buffer_t *iov, int iovcnt); - -/*-- sm3.c --*/ -void _gcry_sm3_hash_buffer (void *outbuf, - const void *buffer, size_t length); -void _gcry_sm3_hash_buffers (void *outbuf, - const gcry_buffer_t *iov, int iovcnt); /*-- blake2.c --*/ gcry_err_code_t _gcry_blake2_init_with_key(void *ctx, unsigned int flags, -- 2.27.0 From jussi.kivilinna at iki.fi Fri Apr 9 18:53:13 2021 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 9 Apr 2021 19:53:13 +0300 Subject: [PATCH 2/3] hash_buffers: add output length param for XOF support In-Reply-To: <20210409165314.1532424-1-jussi.kivilinna@iki.fi> References: <20210409165314.1532424-1-jussi.kivilinna@iki.fi> Message-ID: <20210409165314.1532424-2-jussi.kivilinna@iki.fi> * src/cipher-proto.h (gcry_md_hash_buffers_t): Add nbytes parameter for outbuf size for XOF algorithms. * cipher/md.c (_gcry_md_hash_buffer) (_gcry_md_hash_buffers_extract): Adjust for spec->hash_buffers parameter change. * cipher/keccak.c (_gcry_sha3_hash_buffers): Add nbytes parameter and handling for XOF output. * cipher/blake2.c (DEFINE_BLAKE2_VARIANT): Add nbytes parameter for hash_buffers. * cipher/rmd160.c (_gcry_rmd160_hash_buffers): Add nbytes parameter. * cipher/sha1.c (_gcry_sha1_hash_buffers): Add nbytes parameter. (_gcry_sha1_hash_buffer): Pass nbytes to _gcry_sha1_hash_buffers. * cipher/sha256.c (_gcry_sha256_hash_buffers) (_gcry_sha224_hash_buffers): Add nbytes parameter. * cipher/sha512.c (_gcry_sha512_hash_buffers) (_gcry_sha384_hash_buffers, _gcry_sha512_256_hash_buffers) (_gcry_sha512_224_hash_buffers): Add nbytes parameter. * cipher/sm3.c (_gcry_sm3_hash_buffers): Add nbytes parameter. -- Signed-off-by: Jussi Kivilinna --- cipher/blake2.c | 3 ++- cipher/keccak.c | 37 ++++++++++++++++++++++--------------- cipher/md.c | 4 ++-- cipher/rmd160.c | 5 ++++- cipher/sha1.c | 7 +++++-- cipher/sha256.c | 10 ++++++++-- cipher/sha512.c | 21 +++++++++++++++------ cipher/sm3.c | 5 ++++- src/cipher-proto.h | 5 +++-- 9 files changed, 65 insertions(+), 32 deletions(-) diff --git a/cipher/blake2.c b/cipher/blake2.c index 0243ed33..750c00c3 100644 --- a/cipher/blake2.c +++ b/cipher/blake2.c @@ -946,10 +946,11 @@ gcry_err_code_t _gcry_blake2_init_with_key(void *ctx, unsigned int flags, gcry_assert (err == 0); \ } \ static void \ - _gcry_blake2##bs##_##dbits##_hash_buffers(void *outbuf, \ + _gcry_blake2##bs##_##dbits##_hash_buffers(void *outbuf, size_t nbytes, \ const gcry_buffer_t *iov, int iovcnt) \ { \ BLAKE2##BS##_CONTEXT hd; \ + (void)nbytes; \ blake2##bs##_##dbits##_init (&hd, 0); \ for (;iovcnt > 0; iov++, iovcnt--) \ blake2##bs##_write (&hd, (const char*)iov[0].data + iov[0].off, \ diff --git a/cipher/keccak.c b/cipher/keccak.c index bb643e3d..00593bdb 100644 --- a/cipher/keccak.c +++ b/cipher/keccak.c @@ -1223,8 +1223,8 @@ keccak_extract (void *context, void *out, size_t outlen) /* Variant of the above shortcut function using multiple buffers. */ static void -_gcry_sha3_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt, - const gcry_md_spec_t *spec) +_gcry_sha3_hash_buffers (void *outbuf, size_t nbytes, const gcry_buffer_t *iov, + int iovcnt, const gcry_md_spec_t *spec) { KECCAK_CONTEXT hd; @@ -1232,36 +1232,43 @@ _gcry_sha3_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt, for (;iovcnt > 0; iov++, iovcnt--) keccak_write (&hd, (const char*)iov[0].data + iov[0].off, iov[0].len); keccak_final (&hd); - memcpy (outbuf, keccak_read (&hd), spec->mdlen); + if (spec->mdlen > 0) + memcpy (outbuf, keccak_read (&hd), spec->mdlen); + else + keccak_extract (&hd, outbuf, nbytes); } static void -_gcry_sha3_224_hash_buffers (void *outbuf, const gcry_buffer_t *iov, - int iovcnt) +_gcry_sha3_224_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) { - _gcry_sha3_hash_buffers (outbuf, iov, iovcnt, &_gcry_digest_spec_sha3_224); + _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, + &_gcry_digest_spec_sha3_224); } static void -_gcry_sha3_256_hash_buffers (void *outbuf, const gcry_buffer_t *iov, - int iovcnt) +_gcry_sha3_256_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) { - _gcry_sha3_hash_buffers (outbuf, iov, iovcnt, &_gcry_digest_spec_sha3_256); + _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, + &_gcry_digest_spec_sha3_256); } static void -_gcry_sha3_384_hash_buffers (void *outbuf, const gcry_buffer_t *iov, - int iovcnt) +_gcry_sha3_384_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) { - _gcry_sha3_hash_buffers (outbuf, iov, iovcnt, &_gcry_digest_spec_sha3_384); + _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, + &_gcry_digest_spec_sha3_384); } static void -_gcry_sha3_512_hash_buffers (void *outbuf, const gcry_buffer_t *iov, - int iovcnt) +_gcry_sha3_512_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) { - _gcry_sha3_hash_buffers (outbuf, iov, iovcnt, &_gcry_digest_spec_sha3_512); + _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, + &_gcry_digest_spec_sha3_512); } diff --git a/cipher/md.c b/cipher/md.c index f142e9c3..6497ab41 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -1214,7 +1214,7 @@ _gcry_md_hash_buffer (int algo, void *digest, iov.off = 0; iov.len = length; - spec->hash_buffers (digest, &iov, 1); + spec->hash_buffers (digest, spec->mdlen, &iov, 1); } else { @@ -1294,7 +1294,7 @@ _gcry_md_hash_buffers_extract (int algo, unsigned int flags, void *digest, if (!hmac && spec->hash_buffers) { - spec->hash_buffers (digest, iov, iovcnt); + spec->hash_buffers (digest, digestlen, iov, iovcnt); } else { diff --git a/cipher/rmd160.c b/cipher/rmd160.c index 37462130..1861205e 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -481,10 +481,13 @@ rmd160_read( void *context ) * into outbuf which must have a size of 20 bytes. */ static void -_gcry_rmd160_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) +_gcry_rmd160_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) { RMD160_CONTEXT hd; + (void)nbytes; + rmd160_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, diff --git a/cipher/sha1.c b/cipher/sha1.c index 48fdbb33..3bb24c7e 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -637,10 +637,13 @@ sha1_read( void *context ) * into outbuf which must have a size of 20 bytes. */ static void -_gcry_sha1_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) +_gcry_sha1_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) { SHA1_CONTEXT hd; + (void)nbytes; + sha1_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, @@ -658,7 +661,7 @@ _gcry_sha1_hash_buffer (void *outbuf, const void *buffer, size_t length) iov.data = (void *)buffer; iov.len = length; - _gcry_sha1_hash_buffers (outbuf, &iov, 1); + _gcry_sha1_hash_buffers (outbuf, 20, &iov, 1); } diff --git a/cipher/sha256.c b/cipher/sha256.c index 871615b6..7b2c78f7 100644 --- a/cipher/sha256.c +++ b/cipher/sha256.c @@ -631,10 +631,13 @@ sha256_read (void *context) /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 32 bytes. */ static void -_gcry_sha256_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) +_gcry_sha256_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) { SHA256_CONTEXT hd; + (void)nbytes; + sha256_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, @@ -647,10 +650,13 @@ _gcry_sha256_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 28 bytes. */ static void -_gcry_sha224_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) +_gcry_sha224_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) { SHA256_CONTEXT hd; + (void)nbytes; + sha224_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, diff --git a/cipher/sha512.c b/cipher/sha512.c index a23d5bda..6859cf52 100644 --- a/cipher/sha512.c +++ b/cipher/sha512.c @@ -865,10 +865,13 @@ sha512_read (void *context) /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 64 bytes. */ static void -_gcry_sha512_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) +_gcry_sha512_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) { SHA512_CONTEXT hd; + (void)nbytes; + sha512_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, @@ -882,10 +885,13 @@ _gcry_sha512_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 48 bytes. */ static void -_gcry_sha384_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) +_gcry_sha384_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) { SHA512_CONTEXT hd; + (void)nbytes; + sha384_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, @@ -899,11 +905,12 @@ _gcry_sha384_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 32 bytes. */ static void -_gcry_sha512_256_hash_buffers (void *outbuf, const gcry_buffer_t *iov, - int iovcnt) +_gcry_sha512_256_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) { SHA512_CONTEXT hd; + (void)nbytes; sha512_256_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) @@ -918,11 +925,13 @@ _gcry_sha512_256_hash_buffers (void *outbuf, const gcry_buffer_t *iov, /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 28 bytes. */ static void -_gcry_sha512_224_hash_buffers (void *outbuf, const gcry_buffer_t *iov, - int iovcnt) +_gcry_sha512_224_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) { SHA512_CONTEXT hd; + (void)nbytes; + sha512_224_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, diff --git a/cipher/sm3.c b/cipher/sm3.c index c687cdf0..d52a7494 100644 --- a/cipher/sm3.c +++ b/cipher/sm3.c @@ -341,10 +341,13 @@ sm3_read (void *context) /* Shortcut functions which puts the hash value of the supplied buffer iov * into outbuf which must have a size of 32 bytes. */ static void -_gcry_sm3_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt) +_gcry_sm3_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) { SM3_CONTEXT hd; + (void)nbytes; + sm3_init (&hd, 0); for (;iovcnt > 0; iov++, iovcnt--) _gcry_md_block_write (&hd, diff --git a/src/cipher-proto.h b/src/cipher-proto.h index dde56d30..b730fd06 100644 --- a/src/cipher-proto.h +++ b/src/cipher-proto.h @@ -222,8 +222,9 @@ typedef unsigned char *(*gcry_md_read_t) (void *c); typedef void (*gcry_md_extract_t) (void *c, void *outbuf, size_t nbytes); /* Type for the md_hash_buffers function. */ -typedef void (*gcry_md_hash_buffers_t) (void *outbuf, const gcry_buffer_t *iov, - int iovcnt); +typedef void (*gcry_md_hash_buffers_t) (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, + int iovcnt); typedef struct gcry_md_oid_spec { -- 2.27.0 From jussi.kivilinna at iki.fi Fri Apr 9 18:53:14 2021 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 9 Apr 2021 19:53:14 +0300 Subject: [PATCH 3/3] keccak: add hash_buffers functions for SHAKE128 & SHAKE256 In-Reply-To: <20210409165314.1532424-1-jussi.kivilinna@iki.fi> References: <20210409165314.1532424-1-jussi.kivilinna@iki.fi> Message-ID: <20210409165314.1532424-3-jussi.kivilinna@iki.fi> * cipher/keccak.c (_gcry_shake128_hash_buffers) (_gcry_shake256_hash_buffers): New. (_gcry_digest_spec_shake128, _gcry_digest_spec_shake256): Add hash_buffers pointer. -- Signed-off-by: Jussi Kivilinna --- cipher/keccak.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/cipher/keccak.c b/cipher/keccak.c index 00593bdb..c03a1fac 100644 --- a/cipher/keccak.c +++ b/cipher/keccak.c @@ -1271,6 +1271,22 @@ _gcry_sha3_512_hash_buffers (void *outbuf, size_t nbytes, &_gcry_digest_spec_sha3_512); } +static void +_gcry_shake128_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) +{ + _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, + &_gcry_digest_spec_shake128); +} + +static void +_gcry_shake256_hash_buffers (void *outbuf, size_t nbytes, + const gcry_buffer_t *iov, int iovcnt) +{ + _gcry_sha3_hash_buffers (outbuf, nbytes, iov, iovcnt, + &_gcry_digest_spec_shake256); +} + /* Self-test section. @@ -1530,7 +1546,7 @@ gcry_md_spec_t _gcry_digest_spec_shake128 = GCRY_MD_SHAKE128, {0, 1}, "SHAKE128", shake128_asn, DIM (shake128_asn), oid_spec_shake128, 0, shake128_init, keccak_write, keccak_final, NULL, keccak_extract, - NULL, + _gcry_shake128_hash_buffers, sizeof (KECCAK_CONTEXT), run_selftests }; @@ -1539,7 +1555,7 @@ gcry_md_spec_t _gcry_digest_spec_shake256 = GCRY_MD_SHAKE256, {0, 1}, "SHAKE256", shake256_asn, DIM (shake256_asn), oid_spec_shake256, 0, shake256_init, keccak_write, keccak_final, NULL, keccak_extract, - NULL, + _gcry_shake256_hash_buffers, sizeof (KECCAK_CONTEXT), run_selftests }; -- 2.27.0 From jussi.kivilinna at iki.fi Mon Apr 26 23:00:39 2021 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 27 Apr 2021 00:00:39 +0300 Subject: [PATCH 1/8] tests/benchmark: add benchmark for Ed448 Message-ID: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> * tests/benchmark.c (ecc_bench): Add Ed448. -- Signed-off-by: Jussi Kivilinna --- tests/benchmark.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/tests/benchmark.c b/tests/benchmark.c index 5963527e..605b50c6 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -1475,7 +1475,7 @@ ecc_bench (int iterations, int print_header) { #if USE_ECC gpg_error_t err; - const char *p_sizes[] = { "192", "224", "256", "384", "521", "Ed25519", + const char *p_sizes[] = { "192", "224", "256", "384", "521", "Ed25519", "Ed448", "gost256", "gost512" }; int testno; @@ -1492,14 +1492,17 @@ ecc_bench (int iterations, int print_header) int count; int p_size; int is_ed25519; + int is_ed448; int is_gost; is_ed25519 = !strcmp (p_sizes[testno], "Ed25519"); + is_ed448 = !strcmp (p_sizes[testno], "Ed448"); is_gost = !strncmp (p_sizes[testno], "gost", 4); /* Only P-{224,256,384,521} are allowed in fips mode */ if (gcry_fips_mode_active() - && (is_ed25519 || is_gost || !strcmp (p_sizes[testno], "192"))) + && (is_ed25519 || is_ed448 || is_gost + || !strcmp (p_sizes[testno], "192"))) continue; if (is_ed25519) @@ -1508,6 +1511,12 @@ ecc_bench (int iterations, int print_header) printf ("EdDSA Ed25519 "); fflush (stdout); } + else if (is_ed448) + { + p_size = 448; + printf ("EdDSA Ed448 "); + fflush (stdout); + } else if (is_gost) { p_size = atoi (p_sizes[testno] + 4); @@ -1525,6 +1534,10 @@ ecc_bench (int iterations, int print_header) err = gcry_sexp_build (&key_spec, NULL, "(genkey (ecdsa (curve \"Ed25519\")" "(flags eddsa)))"); + else if (is_ed448) + err = gcry_sexp_build (&key_spec, NULL, + "(genkey (ecdsa (curve \"Ed448\")" + "(flags eddsa)))"); else if (is_gost) err = gcry_sexp_build (&key_spec, NULL, "(genkey (ecdsa (curve %s)))", @@ -1562,6 +1575,10 @@ ecc_bench (int iterations, int print_header) err = gcry_sexp_build (&data, NULL, "(data (flags eddsa)(hash-algo sha512)" " (value %m))", x); + else if (is_ed448) + err = gcry_sexp_build (&data, NULL, + "(data (flags eddsa)(hash-algo shake256)" + " (value %m))", x); else if (is_gost) err = gcry_sexp_build (&data, NULL, "(data (flags gost) (value %m))", x); else -- 2.30.2 From jussi.kivilinna at iki.fi Mon Apr 26 23:00:40 2021 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 27 Apr 2021 00:00:40 +0300 Subject: [PATCH 2/8] tests/bench-slope: add ECC benchmarking In-Reply-To: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> References: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> Message-ID: <20210426210046.4157764-2-jussi.kivilinna@iki.fi> * tests/bench-slope.c (bench_print_result_nsec_per_iteration): New. (bench_print_header_nsec_per_iteration): New. (kdf_bench_one, kdf_bench): Use new print helper functions. [USE_ECC]: New ECC benchmarks. (ecc_bench): New. (print_help): Add 'ecc' option. (main): Add ECC benchmarks. -- Signed-off-by: Jussi Kivilinna --- tests/bench-slope.c | 692 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 640 insertions(+), 52 deletions(-) diff --git a/tests/bench-slope.c b/tests/bench-slope.c index c8647b6b..9b4a139a 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -783,6 +783,54 @@ bench_print_result (double nsecs_per_byte) bench_print_result_std (nsecs_per_byte); } +static void +bench_print_result_nsec_per_iteration (double nsecs_per_iteration) +{ + double cycles_per_iteration; + char nsecpiter_buf[16]; + char cpiter_buf[16]; + char mhz_buf[16]; + + strcpy(cpiter_buf, csv_mode ? "" : "-"); + strcpy(mhz_buf, csv_mode ? "" : "-"); + + double_to_str (nsecpiter_buf, sizeof (nsecpiter_buf), nsecs_per_iteration); + + /* If user didn't provide CPU speed, we cannot show cycles/iter results. */ + if (bench_ghz > 0.0) + { + cycles_per_iteration = nsecs_per_iteration * bench_ghz; + double_to_str (cpiter_buf, sizeof (cpiter_buf), cycles_per_iteration); + double_to_str (mhz_buf, sizeof (mhz_buf), bench_ghz * 1000); + } + + if (csv_mode) + { + if (auto_ghz) + printf ("%s,%s,%s,,,,,,,,,%s,ns/iter,%s,c/iter,%s,Mhz\n", + current_section_name, + current_algo_name ? current_algo_name : "", + current_mode_name ? current_mode_name : "", + nsecpiter_buf, + cpiter_buf, + mhz_buf); + else + printf ("%s,%s,%s,,,,,,,,,%s,ns/iter,%s,c/iter\n", + current_section_name, + current_algo_name ? current_algo_name : "", + current_mode_name ? current_mode_name : "", + nsecpiter_buf, + cpiter_buf); + } + else + { + if (auto_ghz) + printf ("%14s %13s %9s\n", nsecpiter_buf, cpiter_buf, mhz_buf); + else + printf ("%14s %13s\n", nsecpiter_buf, cpiter_buf); + } +} + static void bench_print_section (const char *section_name, const char *print_name) { @@ -819,6 +867,28 @@ bench_print_header (int algo_width, const char *algo_name) } } +static void +bench_print_header_nsec_per_iteration (int algo_width, const char *algo_name) +{ + if (csv_mode) + { + gcry_free (current_algo_name); + current_algo_name = gcry_xstrdup (algo_name); + } + else + { + if (algo_width < 0) + printf (" %-*s | ", -algo_width, algo_name); + else + printf (" %-*s | ", algo_width, algo_name); + + if (auto_ghz) + printf ("%14s %13s %9s\n", "nanosecs/iter", "cycles/iter", "auto Mhz"); + else + printf ("%14s %13s\n", "nanosecs/iter", "cycles/iter"); + } +} + static void bench_print_algo (int algo_width, const char *algo_name) { @@ -1991,11 +2061,7 @@ kdf_bench_one (int algo, int subalgo) struct bench_kdf_mode mode = { &kdf_ops }; struct bench_obj obj = { 0 }; double nsecs_per_iteration; - double cycles_per_iteration; char algo_name[32]; - char nsecpiter_buf[16]; - char cpiter_buf[16]; - char mhz_buf[16]; mode.algo = algo; mode.subalgo = subalgo; @@ -2030,45 +2096,7 @@ kdf_bench_one (int algo, int subalgo) obj.priv = &mode; nsecs_per_iteration = do_slope_benchmark (&obj); - - strcpy(cpiter_buf, csv_mode ? "" : "-"); - strcpy(mhz_buf, csv_mode ? "" : "-"); - - double_to_str (nsecpiter_buf, sizeof (nsecpiter_buf), nsecs_per_iteration); - - /* If user didn't provide CPU speed, we cannot show cycles/iter results. */ - if (bench_ghz > 0.0) - { - cycles_per_iteration = nsecs_per_iteration * bench_ghz; - double_to_str (cpiter_buf, sizeof (cpiter_buf), cycles_per_iteration); - double_to_str (mhz_buf, sizeof (mhz_buf), bench_ghz * 1000); - } - - if (csv_mode) - { - if (auto_ghz) - printf ("%s,%s,%s,,,,,,,,,%s,ns/iter,%s,c/iter,%s,Mhz\n", - current_section_name, - current_algo_name ? current_algo_name : "", - current_mode_name ? current_mode_name : "", - nsecpiter_buf, - cpiter_buf, - mhz_buf); - else - printf ("%s,%s,%s,,,,,,,,,%s,ns/iter,%s,c/iter\n", - current_section_name, - current_algo_name ? current_algo_name : "", - current_mode_name ? current_mode_name : "", - nsecpiter_buf, - cpiter_buf); - } - else - { - if (auto_ghz) - printf ("%14s %13s %9s\n", nsecpiter_buf, cpiter_buf, mhz_buf); - else - printf ("%14s %13s\n", nsecpiter_buf, cpiter_buf); - } + bench_print_result_nsec_per_iteration (nsecs_per_iteration); } void @@ -2079,14 +2107,7 @@ kdf_bench (char **argv, int argc) bench_print_section ("kdf", "KDF"); - if (!csv_mode) - { - printf (" %-*s | ", 24, ""); - if (auto_ghz) - printf ("%14s %13s %9s\n", "nanosecs/iter", "cycles/iter", "auto Mhz"); - else - printf ("%14s %13s\n", "nanosecs/iter", "cycles/iter"); - } + bench_print_header_nsec_per_iteration (24, ""); if (argv && argc) { @@ -2116,13 +2137,571 @@ kdf_bench (char **argv, int argc) } +/************************************************************ ECC benchmarks. */ + +#if USE_ECC +enum bench_ecc_algo +{ + ECC_ALGO_ED25519 = 0, + ECC_ALGO_ED448, + ECC_ALGO_NIST_P192, + ECC_ALGO_NIST_P224, + ECC_ALGO_NIST_P256, + ECC_ALGO_NIST_P384, + ECC_ALGO_NIST_P521, + ECC_ALGO_SECP256K1, + __MAX_ECC_ALGO +}; + +enum bench_ecc_operation +{ + ECC_OPER_MULT = 0, + ECC_OPER_KEYGEN, + ECC_OPER_SIGN, + ECC_OPER_VERIFY, + __MAX_ECC_OPER +}; + +struct bench_ecc_oper +{ + enum bench_ecc_operation oper; + const char *name; + struct bench_ops *ops; + + enum bench_ecc_algo algo; +}; + +struct bench_ecc_mult_hd +{ + gcry_ctx_t ec; + gcry_mpi_t k, x, y; + gcry_mpi_point_t G, Q; +}; + +struct bench_ecc_hd +{ + gcry_sexp_t key_spec; + gcry_sexp_t data; + gcry_sexp_t pub_key; + gcry_sexp_t sec_key; + gcry_sexp_t sig; +}; + + +static const char * +ecc_algo_name (int algo) +{ + switch (algo) + { + case ECC_ALGO_ED25519: + return "Ed25519"; + case ECC_ALGO_ED448: + return "Ed448"; + case ECC_ALGO_NIST_P192: + return "NIST-P192"; + case ECC_ALGO_NIST_P224: + return "NIST-P224"; + case ECC_ALGO_NIST_P256: + return "NIST-P256"; + case ECC_ALGO_NIST_P384: + return "NIST-P384"; + case ECC_ALGO_NIST_P521: + return "NIST-P521"; + case ECC_ALGO_SECP256K1: + return "secp256k1"; + default: + return NULL; + } +} + +static const char * +ecc_algo_curve (int algo) +{ + switch (algo) + { + case ECC_ALGO_ED25519: + return "Ed25519"; + case ECC_ALGO_ED448: + return "Ed448"; + case ECC_ALGO_NIST_P192: + return "NIST P-192"; + case ECC_ALGO_NIST_P224: + return "NIST P-224"; + case ECC_ALGO_NIST_P256: + return "NIST P-256"; + case ECC_ALGO_NIST_P384: + return "NIST P-384"; + case ECC_ALGO_NIST_P521: + return "NIST P-521"; + case ECC_ALGO_SECP256K1: + return "secp256k1"; + default: + return NULL; + } +} + +static int +ecc_nbits (int algo) +{ + switch (algo) + { + case ECC_ALGO_ED25519: + return 255; + case ECC_ALGO_ED448: + return 448; + case ECC_ALGO_NIST_P192: + return 192; + case ECC_ALGO_NIST_P224: + return 224; + case ECC_ALGO_NIST_P256: + return 256; + case ECC_ALGO_NIST_P384: + return 384; + case ECC_ALGO_NIST_P521: + return 521; + case ECC_ALGO_SECP256K1: + return 256; + default: + return 0; + } +} + +static int +ecc_map_name (const char *name) +{ + int i; + + for (i = 0; i < __MAX_ECC_ALGO; i++) + { + if (strcmp(ecc_algo_name(i), name) == 0) + { + return i; + } + } + + return -1; +} + + +static int +bench_ecc_mult_init (struct bench_obj *obj) +{ + struct bench_ecc_oper *oper = obj->priv; + struct bench_ecc_mult_hd *hd; + int p_size = ecc_nbits (oper->algo); + gpg_error_t err; + gcry_mpi_t p; + + obj->min_bufsize = 1; + obj->max_bufsize = 4; + obj->step_size = 1; + obj->num_measure_repetitions = + num_measurement_repetitions / obj->max_bufsize; + + while (obj->num_measure_repetitions == 0) + { + if (obj->max_bufsize == 2) + { + obj->num_measure_repetitions = 2; + } + else + { + obj->max_bufsize--; + obj->num_measure_repetitions = + num_measurement_repetitions / obj->max_bufsize; + } + } + + hd = calloc (1, sizeof(*hd)); + if (!hd) + return -1; + + err = gcry_mpi_ec_new (&hd->ec, NULL, ecc_algo_curve(oper->algo)); + if (err) + { + fprintf (stderr, PGM ": gcry_mpi_ec_new failed: %s\n", + gpg_strerror (err)); + exit (1); + } + hd->G = gcry_mpi_ec_get_point ("g", hd->ec, 1); + hd->Q = gcry_mpi_point_new (0); + hd->x = gcry_mpi_new (0); + hd->y = gcry_mpi_new (0); + hd->k = gcry_mpi_new (p_size); + gcry_mpi_randomize (hd->k, p_size, GCRY_WEAK_RANDOM); + p = gcry_mpi_ec_get_mpi ("p", hd->ec, 1); + gcry_mpi_mod (hd->k, hd->k, p); + gcry_mpi_release (p); + + obj->hd = hd; + return 0; +} + +static void +bench_ecc_mult_free (struct bench_obj *obj) +{ + struct bench_ecc_mult_hd *hd = obj->hd; + + gcry_mpi_release (hd->k); + gcry_mpi_release (hd->y); + gcry_mpi_release (hd->x); + gcry_mpi_point_release (hd->Q); + gcry_mpi_point_release (hd->G); + gcry_ctx_release (hd->ec); + free (hd); + obj->hd = NULL; +} + +static void +bench_ecc_mult_do_bench (struct bench_obj *obj, void *buf, size_t num_iter) +{ + struct bench_ecc_mult_hd *hd = obj->hd; + size_t i; + + (void)buf; + + for (i = 0; i < num_iter; i++) + { + gcry_mpi_ec_mul (hd->Q, hd->k, hd->G, hd->ec); + if (gcry_mpi_ec_get_affine (hd->x, hd->y, hd->Q, hd->ec)) + { + fprintf (stderr, PGM ": gcry_mpi_ec_get_affine failed\n"); + exit (1); + } + } +} + + +static int +bench_ecc_init (struct bench_obj *obj) +{ + struct bench_ecc_oper *oper = obj->priv; + struct bench_ecc_hd *hd; + int p_size = ecc_nbits (oper->algo); + gpg_error_t err; + gcry_mpi_t x; + + obj->min_bufsize = 1; + obj->max_bufsize = 4; + obj->step_size = 1; + obj->num_measure_repetitions = + num_measurement_repetitions / obj->max_bufsize; + + while (obj->num_measure_repetitions == 0) + { + if (obj->max_bufsize == 2) + { + obj->num_measure_repetitions = 2; + } + else + { + obj->max_bufsize--; + obj->num_measure_repetitions = + num_measurement_repetitions / obj->max_bufsize; + } + } + + hd = calloc (1, sizeof(*hd)); + if (!hd) + return -1; + + x = gcry_mpi_new (p_size); + gcry_mpi_randomize (x, p_size, GCRY_WEAK_RANDOM); + + switch (oper->algo) + { + default: + return -1; + + case ECC_ALGO_ED25519: + err = gcry_sexp_build (&hd->key_spec, NULL, + "(genkey (ecdsa (curve \"Ed25519\")" + "(flags eddsa)))"); + if (err) + break; + err = gcry_sexp_build (&hd->data, NULL, + "(data (flags eddsa)(hash-algo sha512)" + " (value %m))", x); + break; + + case ECC_ALGO_ED448: + err = gcry_sexp_build (&hd->key_spec, NULL, + "(genkey (ecdsa (curve \"Ed448\")" + "(flags eddsa)))"); + if (err) + break; + err = gcry_sexp_build (&hd->data, NULL, + "(data (flags eddsa)(hash-algo shake256)" + " (value %m))", x); + break; + + case ECC_ALGO_NIST_P192: + case ECC_ALGO_NIST_P224: + case ECC_ALGO_NIST_P256: + case ECC_ALGO_NIST_P384: + case ECC_ALGO_NIST_P521: + err = gcry_sexp_build (&hd->key_spec, NULL, + "(genkey (ECDSA (nbits %d)))", p_size); + if (err) + break; + err = gcry_sexp_build (&hd->data, NULL, + "(data (flags raw) (value %m))", x); + break; + } + + gcry_mpi_release (x); + + if (err) + { + fprintf (stderr, PGM ": gcry_sexp_build failed: %s\n", + gpg_strerror (err)); + exit (1); + } + + obj->hd = hd; + return 0; +} + +static void +bench_ecc_free (struct bench_obj *obj) +{ + struct bench_ecc_hd *hd = obj->hd; + + gcry_sexp_release (hd->sig); + gcry_sexp_release (hd->pub_key); + gcry_sexp_release (hd->sec_key); + gcry_sexp_release (hd->data); + gcry_sexp_release (hd->key_spec); + free (hd); + obj->hd = NULL; +} + +static void +bench_ecc_keygen (struct bench_ecc_hd *hd) +{ + gcry_sexp_t key_pair; + gpg_error_t err; + + err = gcry_pk_genkey (&key_pair, hd->key_spec); + if (err) + { + fprintf (stderr, PGM ": gcry_pk_genkey failed: %s\n", + gpg_strerror (err)); + exit (1); + } + + hd->pub_key = gcry_sexp_find_token (key_pair, "public-key", 0); + if (!hd->pub_key) + { + fprintf (stderr, PGM ": public part missing in key\n"); + exit (1); + } + hd->sec_key = gcry_sexp_find_token (key_pair, "private-key", 0); + if (!hd->sec_key) + { + fprintf (stderr, PGM ": private part missing in key\n"); + exit (1); + } + + gcry_sexp_release (key_pair); +} + +static void +bench_ecc_keygen_do_bench (struct bench_obj *obj, void *buf, size_t num_iter) +{ + struct bench_ecc_hd *hd = obj->hd; + size_t i; + + (void)buf; + + for (i = 0; i < num_iter; i++) + { + bench_ecc_keygen (hd); + gcry_sexp_release (hd->pub_key); + gcry_sexp_release (hd->sec_key); + } + + hd->pub_key = NULL; + hd->sec_key = NULL; +} + +static void +bench_ecc_sign_do_bench (struct bench_obj *obj, void *buf, size_t num_iter) +{ + struct bench_ecc_hd *hd = obj->hd; + gpg_error_t err; + size_t i; + + (void)buf; + + bench_ecc_keygen (hd); + + for (i = 0; i < num_iter; i++) + { + err = gcry_pk_sign (&hd->sig, hd->data, hd->sec_key); + if (err) + { + fprintf (stderr, PGM ": gcry_pk_sign failed: %s\n", + gpg_strerror (err)); + exit (1); + } + gcry_sexp_release (hd->sig); + } + + gcry_sexp_release (hd->pub_key); + gcry_sexp_release (hd->sec_key); + hd->sig = NULL; + hd->pub_key = NULL; + hd->sec_key = NULL; +} + +static void +bench_ecc_verify_do_bench (struct bench_obj *obj, void *buf, size_t num_iter) +{ + struct bench_ecc_hd *hd = obj->hd; + gpg_error_t err; + int i; + + (void)buf; + + bench_ecc_keygen (hd); + err = gcry_pk_sign (&hd->sig, hd->data, hd->sec_key); + if (err) + { + fprintf (stderr, PGM ": gcry_pk_sign failed: %s\n", + gpg_strerror (err)); + exit (1); + } + + for (i = 0; i < num_iter; i++) + { + err = gcry_pk_verify (hd->sig, hd->data, hd->pub_key); + if (err) + { + fprintf (stderr, PGM ": gcry_pk_verify failed: %s\n", + gpg_strerror (err)); + exit (1); + } + } + + gcry_sexp_release (hd->sig); + gcry_sexp_release (hd->pub_key); + gcry_sexp_release (hd->sec_key); + hd->sig = NULL; + hd->pub_key = NULL; + hd->sec_key = NULL; +} + + +static struct bench_ops ecc_mult_ops = { + &bench_ecc_mult_init, + &bench_ecc_mult_free, + &bench_ecc_mult_do_bench +}; + +static struct bench_ops ecc_keygen_ops = { + &bench_ecc_init, + &bench_ecc_free, + &bench_ecc_keygen_do_bench +}; + +static struct bench_ops ecc_sign_ops = { + &bench_ecc_init, + &bench_ecc_free, + &bench_ecc_sign_do_bench +}; + +static struct bench_ops ecc_verify_ops = { + &bench_ecc_init, + &bench_ecc_free, + &bench_ecc_verify_do_bench +}; + + +static struct bench_ecc_oper ecc_operations[] = { + { ECC_OPER_MULT, "mult", &ecc_mult_ops }, + { ECC_OPER_KEYGEN, "keygen", &ecc_keygen_ops }, + { ECC_OPER_SIGN, "sign", &ecc_sign_ops }, + { ECC_OPER_VERIFY, "verify", &ecc_verify_ops }, + { 0, NULL, NULL } +}; + + +static void +cipher_ecc_one (enum bench_ecc_algo algo, struct bench_ecc_oper *poper) +{ + struct bench_ecc_oper oper = *poper; + struct bench_obj obj = { 0 }; + double result; + + if (algo == ECC_ALGO_SECP256K1 && oper.oper != ECC_OPER_MULT) + return; + + oper.algo = algo; + + bench_print_mode (14, oper.name); + + obj.ops = oper.ops; + obj.priv = &oper; + + result = do_slope_benchmark (&obj); + bench_print_result_nsec_per_iteration (result); +} + + +static void +_ecc_bench (int algo) +{ + const char *algo_name; + int i; + + algo_name = ecc_algo_name (algo); + + bench_print_header_nsec_per_iteration (14, algo_name); + + for (i = 0; ecc_operations[i].name; i++) + cipher_ecc_one (algo, &ecc_operations[i]); + + bench_print_footer (14); +} +#endif + + +void +ecc_bench (char **argv, int argc) +{ +#if USE_ECC + int i, algo; + + bench_print_section ("ecc", "ECC"); + + if (argv && argc) + { + for (i = 0; i < argc; i++) + { + algo = ecc_map_name (argv[i]); + if (algo >= 0) + _ecc_bench (algo); + } + } + else + { + for (i = 0; i < __MAX_ECC_ALGO; i++) + _ecc_bench (i); + } +#else + (void)argv; + (void)argc; +#endif +} + /************************************************************** Main program. */ void print_help (void) { static const char *help_lines[] = { - "usage: bench-slope [options] [hash|mac|cipher|kdf [algonames]]", + "usage: bench-slope [options] [hash|mac|cipher|kdf|ecc [algonames]]", "", " options:", " --cpu-mhz Set CPU speed for calculating cycles", @@ -2304,6 +2883,7 @@ main (int argc, char **argv) mac_bench (NULL, 0); cipher_bench (NULL, 0); kdf_bench (NULL, 0); + ecc_bench (NULL, 0); } else if (!strcmp (*argv, "hash")) { @@ -2337,6 +2917,14 @@ main (int argc, char **argv) warm_up_cpu (); kdf_bench ((argc == 0) ? NULL : argv, argc); } + else if (!strcmp (*argv, "ecc")) + { + argc--; + argv++; + + warm_up_cpu (); + ecc_bench ((argc == 0) ? NULL : argv, argc); + } else { fprintf (stderr, PGM ": unknown argument: %s\n", *argv); -- 2.30.2 From jussi.kivilinna at iki.fi Mon Apr 26 23:00:42 2021 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 27 Apr 2021 00:00:42 +0300 Subject: [PATCH 4/8] mpi/longlong.h: fix missing macro parameter parentheses In-Reply-To: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> References: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> Message-ID: <20210426210046.4157764-4-jussi.kivilinna@iki.fi> * mpi/longlong.h [__alpha] (umul_ppmm): Add parentheses around used parameters. [__i370__] (sdiv_qrnnd): Ditto. [__mips__] (umul_ppmm): Ditto. [__vax__] (sdiv_qrnnd): Ditto. -- Noticed issue after wrong results on mips64 with new mpi/ec code. Signed-off-by: Jussi Kivilinna --- mpi/longlong.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/mpi/longlong.h b/mpi/longlong.h index 6bb6bedf..630993b4 100644 --- a/mpi/longlong.h +++ b/mpi/longlong.h @@ -168,7 +168,7 @@ MA 02111-1307, USA. */ do { \ UDItype __m0 = (m0), __m1 = (m1); \ __asm__ ("umulh %r1,%2,%0" \ - : "=r" ((UDItype) ph) \ + : "=r" ((UDItype)(ph)) \ : "%rJ" (__m0), \ "rI" (__m1)); \ (pl) = __m0 * __m1; \ @@ -498,7 +498,7 @@ extern USItype __udiv_qrnnd (); union {DItype __ll; \ struct {USItype __h, __l;} __i; \ } __xx; \ - __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ __asm__ ("dr %0,%2" \ : "=r" (__xx.__ll) \ : "0" (__xx.__ll), "r" (d)); \ @@ -865,7 +865,7 @@ extern USItype __udiv_qrnnd (); # define umul_ppmm(w1, w0, u, v) \ do { \ UDItype _r; \ - _r = (UDItype) u * v; \ + _r = (UDItype)(u) * (v); \ (w1) = _r >> 32; \ (w0) = (USItype) _r; \ } while (0) @@ -880,7 +880,7 @@ extern USItype __udiv_qrnnd (); # define umul_ppmm(w1, w0, u, v) \ __asm__ ("multu %2,%3 \n" \ "mflo %0 \n" \ - "mfhi %1" \ + "mfhi %1" \ : "=d" ((USItype)(w0)), \ "=d" ((USItype)(w1)) \ : "d" ((USItype)(u)), \ @@ -900,7 +900,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define umul_ppmm(w1, w0, u, v) \ do { \ UTItype _r; \ - _r = (UTItype) u * v; \ + _r = (UTItype)(u) * (v); \ (w1) = _r >> 64; \ (w0) = (UDItype) _r; \ } while (0) @@ -915,7 +915,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI))); # define umul_ppmm(w1, w0, u, v) \ __asm__ ("dmultu %2,%3 \n" \ "mflo %0 \n" \ - "mfhi %1" \ + "mfhi %1" \ : "=d" ((UDItype)(w0)), \ "=d" ((UDItype)(w1)) \ : "d" ((UDItype)(u)), \ @@ -1494,7 +1494,7 @@ extern USItype __udiv_qrnnd (); union {DItype __ll; \ struct {SItype __l, __h;} __i; \ } __xx; \ - __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ __asm__ ("ediv %3,%2,%0,%1" \ : "=g" (q), "=g" (r) \ : "g" (__xx.__ll), "g" (d)); \ -- 2.30.2 From jussi.kivilinna at iki.fi Mon Apr 26 23:00:43 2021 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 27 Apr 2021 00:00:43 +0300 Subject: [PATCH 5/8] mpi/ec: small optimization for ec_mulm_25519 In-Reply-To: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> References: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> Message-ID: <20210426210046.4157764-5-jussi.kivilinna@iki.fi> * mpi/ec.c (ec_addm_25519): Remove one addition. (ec_subm_25519): Change order of add_n and set_cond to remove need to clear 'n'. (ec_mulm_25519): Avoid extra memory copies; Use _gcry_mpih_addmul_1 for multiplying by 19 and adding; Remove one addition at end. -- Benchmarks on AMD Ryzen 7 5800X: Before: Ed25519 | nanosecs/iter cycles/iter auto Mhz keygen | 304980 1478913 4849 sign | 328657 1589657 4837 verify | 625133 3032355 4851 After (~22% faster): Ed25519 | nanosecs/iter cycles/iter auto Mhz keygen | 244288 1184862 4850 sign | 267831 1298934 4850 verify | 504745 2449106 4852 Signed-off-by: Jussi Kivilinna --- mpi/ec.c | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/mpi/ec.c b/mpi/ec.c index 0b6ae9a9..e1d4b32c 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -369,15 +369,13 @@ ec_addm_25519 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize) log_bug ("addm_25519: different sizes\n"); - memset (n, 0, sizeof n); up = u->d; vp = v->d; wp = w->d; _gcry_mpih_add_n (wp, up, vp, wsize); - borrow = _gcry_mpih_sub_n (wp, wp, ctx->p->d, wsize); - mpih_set_cond (n, ctx->p->d, wsize, (borrow != 0UL)); - _gcry_mpih_add_n (wp, wp, n, wsize); + borrow = _gcry_mpih_sub_n (n, wp, ctx->p->d, wsize); + mpih_set_cond (wp, n, wsize, (borrow == 0UL)); wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB)); } @@ -392,14 +390,13 @@ ec_subm_25519 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize) log_bug ("subm_25519: different sizes\n"); - memset (n, 0, sizeof n); up = u->d; vp = v->d; wp = w->d; borrow = _gcry_mpih_sub_n (wp, up, vp, wsize); - mpih_set_cond (n, ctx->p->d, wsize, (borrow != 0UL)); - _gcry_mpih_add_n (wp, wp, n, wsize); + _gcry_mpih_add_n (n, wp, ctx->p->d, wsize); + mpih_set_cond (wp, n, wsize, (borrow != 0UL)); wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB)); } @@ -409,7 +406,6 @@ ec_mulm_25519 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) mpi_ptr_t wp, up, vp; mpi_size_t wsize = LIMB_SIZE_25519; mpi_limb_t n[LIMB_SIZE_25519*2]; - mpi_limb_t m[LIMB_SIZE_25519+1]; mpi_limb_t cy; int msb; @@ -425,32 +421,19 @@ ec_mulm_25519 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) memcpy (wp, n, wsize * BYTES_PER_MPI_LIMB); wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB)); - memcpy (m, n+LIMB_SIZE_25519-1, (wsize+1) * BYTES_PER_MPI_LIMB); - _gcry_mpih_rshift (m, m, LIMB_SIZE_25519+1, (255 % BITS_PER_MPI_LIMB)); - - memcpy (n, m, wsize * BYTES_PER_MPI_LIMB); - cy = _gcry_mpih_lshift (m, m, LIMB_SIZE_25519, 4); - m[LIMB_SIZE_25519] = cy; - cy = _gcry_mpih_add_n (m, m, n, wsize); - m[LIMB_SIZE_25519] += cy; - cy = _gcry_mpih_add_n (m, m, n, wsize); - m[LIMB_SIZE_25519] += cy; - cy = _gcry_mpih_add_n (m, m, n, wsize); - m[LIMB_SIZE_25519] += cy; + _gcry_mpih_rshift (n, n+LIMB_SIZE_25519-1, LIMB_SIZE_25519+1, + (255 % BITS_PER_MPI_LIMB)); - cy = _gcry_mpih_add_n (wp, wp, m, wsize); - m[LIMB_SIZE_25519] += cy; + cy = _gcry_mpih_addmul_1 (wp, n, wsize, 19); - memset (m, 0, wsize * BYTES_PER_MPI_LIMB); + memset (n, 0, wsize * BYTES_PER_MPI_LIMB); msb = (wp[LIMB_SIZE_25519-1] >> (255 % BITS_PER_MPI_LIMB)); - m[0] = (m[LIMB_SIZE_25519] * 2 + msb) * 19; + n[0] = (cy * 2 + msb) * 19; wp[LIMB_SIZE_25519-1] &= ~((mpi_limb_t)1 << (255 % BITS_PER_MPI_LIMB)); - _gcry_mpih_add_n (wp, wp, m, wsize); + _gcry_mpih_add_n (wp, wp, n, wsize); - m[0] = 0; - cy = _gcry_mpih_sub_n (wp, wp, ctx->p->d, wsize); - mpih_set_cond (m, ctx->p->d, wsize, (cy != 0UL)); - _gcry_mpih_add_n (wp, wp, m, wsize); + cy = _gcry_mpih_sub_n (n, wp, ctx->p->d, wsize); + mpih_set_cond (wp, n, wsize, (cy == 0UL)); } static void -- 2.30.2 From jussi.kivilinna at iki.fi Mon Apr 26 23:00:44 2021 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 27 Apr 2021 00:00:44 +0300 Subject: [PATCH 6/8] mpi/ec: small optimization for ec_mulm_448 In-Reply-To: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> References: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> Message-ID: <20210426210046.4157764-6-jussi.kivilinna@iki.fi> * mpi/ec.c (ec_addm_448, ec_subm_448): Change order of sub_n and set_cond to remove need to clear 'n'. (ec_mulm_448): Use memcpy where possible; Use mpih_rshift where possible; Use mpih_lshift for doubling a3; Remove one addition at end. -- Benchmarks on AMD Ryzen 7 5800X: Before: Ed448 | nanosecs/iter cycles/iter auto Mhz keygen | 893096 4343326 4863 sign | 988422 4795694 4852 verify | 1899706 9215952 4851 After (~5% faster): Ed448 | nanosecs/iter cycles/iter auto Mhz keygen | 822078 3987952 4851 sign | 947327 4595433 4851 verify | 1776259 8616675 4851 Signed-off-by: Jussi Kivilinna --- mpi/ec.c | 76 ++++++++++++++++---------------------------------------- 1 file changed, 22 insertions(+), 54 deletions(-) diff --git a/mpi/ec.c b/mpi/ec.c index e1d4b32c..4fabf9b4 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -464,14 +464,13 @@ ec_addm_448 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize) log_bug ("addm_448: different sizes\n"); - memset (n, 0, sizeof n); up = u->d; vp = v->d; wp = w->d; cy = _gcry_mpih_add_n (wp, up, vp, wsize); - mpih_set_cond (n, ctx->p->d, wsize, (cy != 0UL)); - _gcry_mpih_sub_n (wp, wp, n, wsize); + _gcry_mpih_sub_n (n, wp, ctx->p->d, wsize); + mpih_set_cond (wp, n, wsize, (cy != 0UL)); } static void @@ -485,14 +484,13 @@ ec_subm_448 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize) log_bug ("subm_448: different sizes\n"); - memset (n, 0, sizeof n); up = u->d; vp = v->d; wp = w->d; borrow = _gcry_mpih_sub_n (wp, up, vp, wsize); - mpih_set_cond (n, ctx->p->d, wsize, (borrow != 0UL)); - _gcry_mpih_add_n (wp, wp, n, wsize); + _gcry_mpih_add_n (n, wp, ctx->p->d, wsize); + mpih_set_cond (wp, n, wsize, (borrow != 0UL)); } static void @@ -506,10 +504,6 @@ ec_mulm_448 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) mpi_limb_t b0[LIMB_SIZE_HALF_448]; mpi_limb_t b1[LIMB_SIZE_HALF_448]; mpi_limb_t cy; - int i; -#if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2) - mpi_limb_t b1_rest, a3_rest; -#endif if (w->nlimbs != wsize || u->nlimbs != wsize || v->nlimbs != wsize) log_bug ("mulm_448: different sizes\n"); @@ -520,61 +514,37 @@ ec_mulm_448 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) _gcry_mpih_mul_n (n, up, vp, wsize); - for (i = 0; i < (wsize + 1)/ 2; i++) - { - b0[i] = n[i]; - b1[i] = n[i+wsize/2]; - a2[i] = n[i+wsize]; - a3[i] = n[i+wsize+wsize/2]; - } + memcpy (b0, n, LIMB_SIZE_HALF_448 * BYTES_PER_MPI_LIMB); + memcpy (a2, n + wsize, LIMB_SIZE_HALF_448 * BYTES_PER_MPI_LIMB); #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2) b0[LIMB_SIZE_HALF_448-1] &= ((mpi_limb_t)1UL<<32)-1; a2[LIMB_SIZE_HALF_448-1] &= ((mpi_limb_t)1UL<<32)-1; - - b1_rest = 0; - a3_rest = 0; - - for (i = (wsize + 1)/ 2 -1; i >= 0; i--) - { - mpi_limb_t b1v, a3v; - b1v = b1[i]; - a3v = a3[i]; - b1[i] = (b1_rest<<32) | (b1v >> 32); - a3[i] = (a3_rest<<32) | (a3v >> 32); - b1_rest = b1v & (((mpi_limb_t)1UL <<32)-1); - a3_rest = a3v & (((mpi_limb_t)1UL <<32)-1); - } + _gcry_mpih_rshift (b1, n + wsize/2, LIMB_SIZE_HALF_448, 32); + _gcry_mpih_rshift (a3, n + wsize + wsize/2, LIMB_SIZE_HALF_448, 32); +#else + memcpy (b1, n + wsize/2, LIMB_SIZE_HALF_448 * BYTES_PER_MPI_LIMB); + memcpy (a3, n + wsize + wsize/2, LIMB_SIZE_HALF_448 * BYTES_PER_MPI_LIMB); #endif cy = _gcry_mpih_add_n (b0, b0, a2, LIMB_SIZE_HALF_448); - cy += _gcry_mpih_add_n (b0, b0, a3, LIMB_SIZE_HALF_448); - for (i = 0; i < (wsize + 1)/ 2; i++) - wp[i] = b0[i]; + cy += _gcry_mpih_add_n (wp, b0, a3, LIMB_SIZE_HALF_448); #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2) + cy = wp[LIMB_SIZE_HALF_448-1] >> 32; wp[LIMB_SIZE_HALF_448-1] &= (((mpi_limb_t)1UL <<32)-1); #endif + memset (b0, 0, LIMB_SIZE_HALF_448 * BYTES_PER_MPI_LIMB); + b0[0] = cy; -#if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2) - cy = b0[LIMB_SIZE_HALF_448-1] >> 32; -#endif - - cy = _gcry_mpih_add_1 (b1, b1, LIMB_SIZE_HALF_448, cy); + cy = _gcry_mpih_add_n (b1, b1, b0, LIMB_SIZE_HALF_448); + cy += _gcry_mpih_lshift (a3, a3, LIMB_SIZE_HALF_448, 1); cy += _gcry_mpih_add_n (b1, b1, a2, LIMB_SIZE_HALF_448); cy += _gcry_mpih_add_n (b1, b1, a3, LIMB_SIZE_HALF_448); - cy += _gcry_mpih_add_n (b1, b1, a3, LIMB_SIZE_HALF_448); #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2) - b1_rest = 0; - for (i = (wsize + 1)/ 2 -1; i >= 0; i--) - { - mpi_limb_t b1v = b1[i]; - b1[i] = (b1_rest<<32) | (b1v >> 32); - b1_rest = b1v & (((mpi_limb_t)1UL <<32)-1); - } - wp[LIMB_SIZE_HALF_448-1] |= (b1_rest << 32); + cy = _gcry_mpih_rshift (b1, b1, LIMB_SIZE_HALF_448, 32); + wp[LIMB_SIZE_HALF_448-1] |= cy; #endif - for (i = 0; i < wsize / 2; i++) - wp[i+(wsize + 1) / 2] = b1[i]; + memcpy (wp + LIMB_SIZE_HALF_448, b1, (wsize / 2) * BYTES_PER_MPI_LIMB); #if (LIMB_SIZE_HALF_448 > LIMB_SIZE_448/2) cy = b1[LIMB_SIZE_HALF_448-1]; @@ -590,10 +560,8 @@ ec_mulm_448 (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) n[0] = cy; _gcry_mpih_add_n (wp, wp, n, wsize); - memset (n, 0, wsize * BYTES_PER_MPI_LIMB); - cy = _gcry_mpih_sub_n (wp, wp, ctx->p->d, wsize); - mpih_set_cond (n, ctx->p->d, wsize, (cy != 0UL)); - _gcry_mpih_add_n (wp, wp, n, wsize); + cy = _gcry_mpih_sub_n (n, wp, ctx->p->d, wsize); + mpih_set_cond (wp, n, wsize, (cy == 0UL)); } static void -- 2.30.2 From jussi.kivilinna at iki.fi Mon Apr 26 23:00:46 2021 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 27 Apr 2021 00:00:46 +0300 Subject: [PATCH 8/8] mpi/ec: add fast reduction for secp256k1 In-Reply-To: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> References: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> Message-ID: <20210426210046.4157764-8-jussi.kivilinna@iki.fi> * mpi/ec.c (ec_secp256k1_mod): New. (field_table): Add 'secp256k1'. * tests/t-mpi-point.c (check_ec_mul): Add secp256k1 test vectors. -- Benchmark on Ryzen 7 5800X (x86_64): Before: secp256k1 | nanosecs/iter cycles/iter auto Mhz mult | 482336 2340443 4852 After (~20% faster): secp256k1 | nanosecs/iter cycles/iter auto Mhz mult | 392941 1906540 4852 Signed-off-by: Jussi Kivilinna --- mpi/ec.c | 62 +++++++++ tests/t-mpi-point.c | 304 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 366 insertions(+) diff --git a/mpi/ec.c b/mpi/ec.c index ae1d036a..29b2ce30 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -576,6 +576,59 @@ ec_pow2_448 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx) ec_mulm_448 (w, b, b, ctx); } + +/* Fast reduction for secp256k1 */ +static void +ec_secp256k1_mod (gcry_mpi_t w, mpi_ec_t ctx) +{ + mpi_size_t wsize = (256 + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB; + mpi_limb_t n[wsize + 1]; + mpi_limb_t s[wsize + 1]; + mpi_limb_t cy, borrow; + mpi_ptr_t wp; + + MPN_NORMALIZE (w->d, w->nlimbs); + if (w->nlimbs > 2 * 256 / BITS_PER_MPI_LIMB) + log_bug ("W must be less than m^2\n"); + + RESIZE_AND_CLEAR_IF_NEEDED (w, wsize * 2); + + wp = w->d; + + /* mod P (2^256 - 2^32 - 977) */ + + /* first pass of reduction */ + memcpy (n, wp + wsize, wsize * BYTES_PER_MPI_LIMB); +#if BITS_PER_MPI_LIMB == 64 + s[wsize] = _gcry_mpih_lshift (s, wp + wsize, wsize, 32); +#else + s[0] = 0; + memcpy (s + 1, wp + wsize, wsize * BYTES_PER_MPI_LIMB); +#endif + wp[wsize] = _gcry_mpih_addmul_1 (wp, n, wsize, 977); + cy = _gcry_mpih_add_n (wp, wp, s, wsize + 1); + + /* second pass of reduction */ +#if BITS_PER_MPI_LIMB == 64 + /* cy == 0 */ + memset (n + 1, 0, (wsize - 1) * BYTES_PER_MPI_LIMB); + umul_ppmm(n[1], n[0], wp[wsize], ((mpi_limb_t)1 << 32) + 977); +#else + memset (n + 2, 0, (wsize - 2) * BYTES_PER_MPI_LIMB); + umul_ppmm(n[1], n[0], wp[wsize], 977); + add_ssaaaa(n[2], n[1], 0, n[1], 0, cy * 977); + add_ssaaaa(n[2], n[1], n[2], n[1], cy, wp[wsize]); +#endif + cy = _gcry_mpih_add_n (wp, wp, n, wsize); + + borrow = _gcry_mpih_sub_n (s, wp, ctx->p->d, wsize); + mpih_set_cond (wp, s, wsize, (cy != 0UL) | (borrow == 0UL)); + + w->nlimbs = wsize; + MPN_NORMALIZE (wp, w->nlimbs); +} + + struct field_table { const char *p; @@ -655,6 +708,15 @@ static const struct field_table field_table[] = { NULL, _gcry_mpi_ec_nist521_mod }, + { + "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", + NULL, + NULL, + NULL, + NULL, + NULL, + ec_secp256k1_mod + }, { NULL, NULL, NULL, NULL, NULL, NULL }, }; diff --git a/tests/t-mpi-point.c b/tests/t-mpi-point.c index 0c4d8905..6cd030f1 100644 --- a/tests/t-mpi-point.c +++ b/tests/t-mpi-point.c @@ -3204,6 +3204,302 @@ check_ec_mul (void) "68118D66A10BD9BF3AAF46FEC052F89ECAC38F795D8D3DBF77416B89602E99AF" }, + /* secp256k1 test-vectors from + https://chuckbatson.wordpress.com/2014/11/26/secp256k1-test-vectors/ */ + { /* tv 260 */ + "secp256k1", + "1", + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8" + }, + { /* tv 261 */ + "secp256k1", + "2", + "C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5", + "1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A" + }, + { /* tv 262 */ + "secp256k1", + "3", + "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "388F7B0F632DE8140FE337E62A37F3566500A99934C2231B6CB9FD7584B8E672" + }, + { /* tv 263 */ + "secp256k1", + "4", + "E493DBF1C10D80F3581E4904930B1404CC6C13900EE0758474FA94ABE8C4CD13", + "51ED993EA0D455B75642E2098EA51448D967AE33BFBDFE40CFE97BDC47739922" + }, + { /* tv 264 */ + "secp256k1", + "5", + "2F8BDE4D1A07209355B4A7250A5C5128E88B84BDDC619AB7CBA8D569B240EFE4", + "D8AC222636E5E3D6D4DBA9DDA6C9C426F788271BAB0D6840DCA87D3AA6AC62D6" + }, + { /* tv 265 */ + "secp256k1", + "6", + "FFF97BD5755EEEA420453A14355235D382F6472F8568A18B2F057A1460297556", + "AE12777AACFBB620F3BE96017F45C560DE80F0F6518FE4A03C870C36B075F297" + }, + { /* tv 266 */ + "secp256k1", + "7", + "5CBDF0646E5DB4EAA398F365F2EA7A0E3D419B7E0330E39CE92BDDEDCAC4F9BC", + "6AEBCA40BA255960A3178D6D861A54DBA813D0B813FDE7B5A5082628087264DA" + }, + { /* tv 267 */ + "secp256k1", + "8", + "2F01E5E15CCA351DAFF3843FB70F3C2F0A1BDD05E5AF888A67784EF3E10A2A01", + "5C4DA8A741539949293D082A132D13B4C2E213D6BA5B7617B5DA2CB76CBDE904" + }, + { /* tv 268 */ + "secp256k1", + "9", + "ACD484E2F0C7F65309AD178A9F559ABDE09796974C57E714C35F110DFC27CCBE", + "CC338921B0A7D9FD64380971763B61E9ADD888A4375F8E0F05CC262AC64F9C37" + }, + { /* tv 269 */ + "secp256k1", + "10", + "A0434D9E47F3C86235477C7B1AE6AE5D3442D49B1943C2B752A68E2A47E247C7", + "893ABA425419BC27A3B6C7E693A24C696F794C2ED877A1593CBEE53B037368D7" + }, + { /* tv 270 */ + "secp256k1", + "11", + "774AE7F858A9411E5EF4246B70C65AAC5649980BE5C17891BBEC17895DA008CB", + "D984A032EB6B5E190243DD56D7B7B365372DB1E2DFF9D6A8301D74C9C953C61B" + }, + { /* tv 271 */ + "secp256k1", + "12", + "D01115D548E7561B15C38F004D734633687CF4419620095BC5B0F47070AFE85A", + "A9F34FFDC815E0D7A8B64537E17BD81579238C5DD9A86D526B051B13F4062327" + }, + { /* tv 272 */ + "secp256k1", + "13", + "F28773C2D975288BC7D1D205C3748651B075FBC6610E58CDDEEDDF8F19405AA8", + "0AB0902E8D880A89758212EB65CDAF473A1A06DA521FA91F29B5CB52DB03ED81" + }, + { /* tv 273 */ + "secp256k1", + "14", + "499FDF9E895E719CFD64E67F07D38E3226AA7B63678949E6E49B241A60E823E4", + "CAC2F6C4B54E855190F044E4A7B3D464464279C27A3F95BCC65F40D403A13F5B" + }, + { /* tv 274 */ + "secp256k1", + "15", + "D7924D4F7D43EA965A465AE3095FF41131E5946F3C85F79E44ADBCF8E27E080E", + "581E2872A86C72A683842EC228CC6DEFEA40AF2BD896D3A5C504DC9FF6A26B58" + }, + { /* tv 275 */ + "secp256k1", + "16", + "E60FCE93B59E9EC53011AABC21C23E97B2A31369B87A5AE9C44EE89E2A6DEC0A", + "F7E3507399E595929DB99F34F57937101296891E44D23F0BE1F32CCE69616821" + }, + { /* tv 276 */ + "secp256k1", + "17", + "DEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34", + "4211AB0694635168E997B0EAD2A93DAECED1F4A04A95C0F6CFB199F69E56EB77" + }, + { /* tv 277 */ + "secp256k1", + "18", + "5601570CB47F238D2B0286DB4A990FA0F3BA28D1A319F5E7CF55C2A2444DA7CC", + "C136C1DC0CBEB930E9E298043589351D81D8E0BC736AE2A1F5192E5E8B061D58" + }, + { /* tv 278 */ + "secp256k1", + "19", + "2B4EA0A797A443D293EF5CFF444F4979F06ACFEBD7E86D277475656138385B6C", + "85E89BC037945D93B343083B5A1C86131A01F60C50269763B570C854E5C09B7A" + }, + { /* tv 279 */ + "secp256k1", + "20", + "4CE119C96E2FA357200B559B2F7DD5A5F02D5290AFF74B03F3E471B273211C97", + "12BA26DCB10EC1625DA61FA10A844C676162948271D96967450288EE9233DC3A" + }, + { /* tv 280 */ + "secp256k1", + "112233445566778899", + "A90CC3D3F3E146DAADFC74CA1372207CB4B725AE708CEF713A98EDD73D99EF29", + "5A79D6B289610C68BC3B47F3D72F9788A26A06868B4D8E433E1E2AD76FB7DC76" + }, + { /* tv 281 */ + "secp256k1", + "112233445566778899112233445566778899", + "E5A2636BCFD412EBF36EC45B19BFB68A1BC5F8632E678132B885F7DF99C5E9B3", + "736C1CE161AE27B405CAFD2A7520370153C2C861AC51D6C1D5985D9606B45F39" + }, + { /* tv 282 */ + "secp256k1", + "28948022309329048855892746252171976963209391069768726095651290785379" + "540373584", + "A6B594B38FB3E77C6EDF78161FADE2041F4E09FD8497DB776E546C41567FEB3C", + "71444009192228730CD8237A490FEBA2AFE3D27D7CC1136BC97E439D13330D55" + }, + { /* tv 283 */ + "secp256k1", + "57896044618658097711785492504343953926418782139537452191302581570759" + "080747168", + "00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63", + "3F3979BF72AE8202983DC989AEC7F2FF2ED91BDD69CE02FC0700CA100E59DDF3" + }, + { /* tv 284 */ + "secp256k1", + "86844066927987146567678238756515930889628173209306178286953872356138" + "621120752", + "E24CE4BEEE294AA6350FAA67512B99D388693AE4E7F53D19882A6EA169FC1CE1", + "8B71E83545FC2B5872589F99D948C03108D36797C4DE363EBD3FF6A9E1A95B10" + }, + { /* tv 285 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494317", + "4CE119C96E2FA357200B559B2F7DD5A5F02D5290AFF74B03F3E471B273211C97", + "ED45D9234EF13E9DA259E05EF57BB3989E9D6B7D8E269698BAFD77106DCC1FF5" + }, + { /* tv 286 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494318", + "2B4EA0A797A443D293EF5CFF444F4979F06ACFEBD7E86D277475656138385B6C", + "7A17643FC86BA26C4CBCF7C4A5E379ECE5FE09F3AFD9689C4A8F37AA1A3F60B5" + }, + { /* tv 287 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494319", + "5601570CB47F238D2B0286DB4A990FA0F3BA28D1A319F5E7CF55C2A2444DA7CC", + "3EC93E23F34146CF161D67FBCA76CAE27E271F438C951D5E0AE6D1A074F9DED7" + }, + { /* tv 288 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494320", + "DEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34", + "BDEE54F96B9CAE9716684F152D56C251312E0B5FB56A3F09304E660861A910B8" + }, + { /* tv 289 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494321", + "E60FCE93B59E9EC53011AABC21C23E97B2A31369B87A5AE9C44EE89E2A6DEC0A", + "081CAF8C661A6A6D624660CB0A86C8EFED6976E1BB2DC0F41E0CD330969E940E" + }, + { /* tv 290 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494322", + "D7924D4F7D43EA965A465AE3095FF41131E5946F3C85F79E44ADBCF8E27E080E", + "A7E1D78D57938D597C7BD13DD733921015BF50D427692C5A3AFB235F095D90D7" + }, + { /* tv 291 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494323", + "499FDF9E895E719CFD64E67F07D38E3226AA7B63678949E6E49B241A60E823E4", + "353D093B4AB17AAE6F0FBB1B584C2B9BB9BD863D85C06A4339A0BF2AFC5EBCD4" + }, + { /* tv 292 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494324", + "F28773C2D975288BC7D1D205C3748651B075FBC6610E58CDDEEDDF8F19405AA8", + "F54F6FD17277F5768A7DED149A3250B8C5E5F925ADE056E0D64A34AC24FC0EAE" + }, + { /* tv 293 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494325", + "D01115D548E7561B15C38F004D734633687CF4419620095BC5B0F47070AFE85A", + "560CB00237EA1F285749BAC81E8427EA86DC73A2265792AD94FAE4EB0BF9D908" + }, + { /* tv 294 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494326", + "774AE7F858A9411E5EF4246B70C65AAC5649980BE5C17891BBEC17895DA008CB", + "267B5FCD1494A1E6FDBC22A928484C9AC8D24E1D20062957CFE28B3536AC3614" + }, + { /* tv 295 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494327", + "A0434D9E47F3C86235477C7B1AE6AE5D3442D49B1943C2B752A68E2A47E247C7", + "76C545BDABE643D85C4938196C5DB3969086B3D127885EA6C3411AC3FC8C9358" + }, + { /* tv 296 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494328", + "ACD484E2F0C7F65309AD178A9F559ABDE09796974C57E714C35F110DFC27CCBE", + "33CC76DE4F5826029BC7F68E89C49E165227775BC8A071F0FA33D9D439B05FF8" + }, + { /* tv 297 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494329", + "2F01E5E15CCA351DAFF3843FB70F3C2F0A1BDD05E5AF888A67784EF3E10A2A01", + "A3B25758BEAC66B6D6C2F7D5ECD2EC4B3D1DEC2945A489E84A25D3479342132B" + }, + { /* tv 298 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494330", + "5CBDF0646E5DB4EAA398F365F2EA7A0E3D419B7E0330E39CE92BDDEDCAC4F9BC", + "951435BF45DAA69F5CE8729279E5AB2457EC2F47EC02184A5AF7D9D6F78D9755" + }, + { /* tv 299 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494331", + "FFF97BD5755EEEA420453A14355235D382F6472F8568A18B2F057A1460297556", + "51ED8885530449DF0C4169FE80BA3A9F217F0F09AE701B5FC378F3C84F8A0998" + }, + { /* tv 300 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494332", + "2F8BDE4D1A07209355B4A7250A5C5128E88B84BDDC619AB7CBA8D569B240EFE4", + "2753DDD9C91A1C292B24562259363BD90877D8E454F297BF235782C459539959" + }, + { /* tv 301 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494333", + "E493DBF1C10D80F3581E4904930B1404CC6C13900EE0758474FA94ABE8C4CD13", + "AE1266C15F2BAA48A9BD1DF6715AEBB7269851CC404201BF30168422B88C630D" + }, + { /* tv 302 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494334", + "F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9", + "C77084F09CD217EBF01CC819D5C80CA99AFF5666CB3DDCE4934602897B4715BD" + }, + { /* tv 303 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494335", + "C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5", + "E51E970159C23CC65C3A7BE6B99315110809CD9ACD992F1EDC9BCE55AF301705" + }, + { /* tv 304 */ + "secp256k1", + "11579208923731619542357098500868790785283756427907490438260516314151" + "8161494336", + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + "B7C52588D95C3B9AA25B0403F1EEF75702E84BB7597AABE663B82F6F04EF2777" + }, + { NULL, NULL, NULL, NULL } }; gpg_error_t err; @@ -3225,6 +3521,14 @@ check_ec_mul (void) once = 1; continue; } + if (!strcmp(tv[idx].curve, "secp256k1")) + { + static int once; + if (!once) + info ("skipping %s in fips mode\n", tv[idx].curve); + once = 1; + continue; + } } err = gcry_mpi_ec_new (&ctx, NULL, tv[idx].curve); -- 2.30.2 From jussi.kivilinna at iki.fi Mon Apr 26 23:00:41 2021 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 27 Apr 2021 00:00:41 +0300 Subject: [PATCH 3/8] tests/t-mpi-point: add NIST curve multiplication test vectors In-Reply-To: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> References: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> Message-ID: <20210426210046.4157764-3-jussi.kivilinna@iki.fi> * tests/t-mpi-point.c (mpi_base10_scan, check_ec_mul): New. (main): Call 'check_ec_mul'. -- These vectors are from: http://point-at-infinity.org/ecc/nisttv Signed-off-by: Jussi Kivilinna --- tests/t-mpi-point.c | 1998 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 1997 insertions(+), 1 deletion(-) diff --git a/tests/t-mpi-point.c b/tests/t-mpi-point.c index 4e555290..0c4d8905 100644 --- a/tests/t-mpi-point.c +++ b/tests/t-mpi-point.c @@ -29,7 +29,7 @@ #define PGM "t-mpi-point" #include "t-common.h" -static struct +static const struct { const char *desc; /* Description of the curve. */ const char *p; /* Order of the prime field. */ @@ -1287,6 +1287,2001 @@ point_on_curve (void) } +static gcry_mpi_t +mpi_base10_scan (const char *str) +{ + gcry_mpi_t k; + + k = gcry_mpi_new (0); + + while (*str) + { + gcry_mpi_mul_ui (k, k, 10); + gcry_mpi_add_ui (k, k, *str - '0'); + str++; + } + + return k; +} + + +static void +check_ec_mul (void) +{ + static struct { + const char *curve; + const char *k_base10; + const char *qx; + const char *qy; + } tv[] = { + /* NIST EC test vectors from http://point-at-infinity.org/ecc/nisttv */ + { /* tv 0 */ + "NIST P-192", + "1", + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811" + }, + { /* tv 1 */ + "NIST P-192", + "2", + "DAFEBF5828783F2AD35534631588A3F629A70FB16982A888", + "DD6BDA0D993DA0FA46B27BBC141B868F59331AFA5C7E93AB" + }, + { /* tv 2 */ + "NIST P-192", + "3", + "76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA", + "782C37E372BA4520AA62E0FED121D49EF3B543660CFD05FD" + }, + { /* tv 3 */ + "NIST P-192", + "4", + "35433907297CC378B0015703374729D7A4FE46647084E4BA", + "A2649984F2135C301EA3ACB0776CD4F125389B311DB3BE32" + }, + { /* tv 4 */ + "NIST P-192", + "5", + "10BB8E9840049B183E078D9C300E1605590118EBDD7FF590", + "31361008476F917BADC9F836E62762BE312B72543CCEAEA1" + }, + { /* tv 5 */ + "NIST P-192", + "6", + "A37ABC6C431F9AC398BF5BD1AA6678320ACE8ECB93D23F2A", + "851B3CAEC99908DBFED7040A1BBDA90E081F7C5710BC68F0" + }, + { /* tv 6 */ + "NIST P-192", + "7", + "8DA75A1F75DDCD7660F923243060EDCE5DE37F007011FCFD", + "57CB5FCF6860B35418240DB8FDB3C01DD4B702F96409FFB5" + }, + { /* tv 7 */ + "NIST P-192", + "8", + "2FA1F92D1ECCE92014771993CC14899D4B5977883397EDDE", + "A338AFDEF78B7214273B8B5978EF733FF2DD8A8E9738F6C0" + }, + { /* tv 8 */ + "NIST P-192", + "9", + "818A4D308B1CABB74E9E8F2BA8D27C9E1D9D375AB980388F", + "01D1AA5E208D87CD7C292F7CBB457CDF30EA542176C8E739" + }, + { /* tv 9 */ + "NIST P-192", + "10", + "AA7C4F9EF99E3E96D1AEDE2BD9238842859BB150D1FE9D85", + "3212A36547EDC62901EE3658B2F4859460EB5EB2491397B0" + }, + { /* tv 10 */ + "NIST P-192", + "11", + "1C995995EB76324F1844F7164D22B652280940370628A2AA", + "EF1765CE37E9EB73029F556400FA77BDB34CB8611AAA9C04" + }, + { /* tv 11 */ + "NIST P-192", + "12", + "1061343F3D456D0ECA013877F8C9E7B28FCCDCDA67EEB8AB", + "5A064CAA2EA6B03798FEF8E3E7A48648681EAC020B27293F" + }, + { /* tv 12 */ + "NIST P-192", + "13", + "112AF141D33EFB9F2F68821E051E4EA004144A363C4A090A", + "6E0CBE3BFC5293F72A2C1726E081E09E7F10A094432B1C1E" + }, + { /* tv 13 */ + "NIST P-192", + "14", + "13B9310646EBC93B591746B3F7C64E05DEE08843DE1081C1", + "1EDCEA63B44142DD15F3B427EC41A1EC4FBACA95E186E6B4" + }, + { /* tv 14 */ + "NIST P-192", + "15", + "8C9595E63B56B633BA3546B2B5414DE736DE4A9E7578B1E7", + "266B762A934F00C17CF387993AA566B6AD7537CDD98FC7B1" + }, + { /* tv 15 */ + "NIST P-192", + "16", + "B7310B4548FBFDBD29005092A5355BFCD99473733048AFDF", + "FF9EAE9EDCD27C1E42D8585C4546D9491845C56629CF2290" + }, + { /* tv 16 */ + "NIST P-192", + "17", + "44275CD2E1F46DC3F9F57636C2B4213B8BB445930510FF8A", + "EFAD8348FDE30C87DE438612A818E98D9B76A67AD25DDFD0" + }, + { /* tv 17 */ + "NIST P-192", + "18", + "C1B4DB0227210613A6CA15C428024E40B6513365D72591A3", + "1E26B286BCA1D08F4FE8F801267DF9FD7782EC3EC3F47F53" + }, + { /* tv 18 */ + "NIST P-192", + "19", + "C0626BCF247DE5D307FD839238D72688774FC97A1CF8AD1B", + "9CDC99D753973DC197E12778E829C804EC1A6B4E71FAA20A" + }, + { /* tv 19 */ + "NIST P-192", + "20", + "BB6F082321D34DBD786A1566915C6DD5EDF879AB0F5ADD67", + "91E4DD8A77C4531C8B76DEF2E5339B5EB95D5D9479DF4C8D" + }, + { /* tv 20 */ + "NIST P-192", + "112233445566778899", + "81E6E0F14C9302C8A8DCA8A038B73165E9687D0490CD9F85", + "F58067119EED8579388C4281DC645A27DB7764750E812477" + }, + { /* tv 21 */ + "NIST P-192", + "112233445566778899112233445566778899", + "B357B10AC985C891B29FB37DA56661CCCF50CEC21128D4F6", + "BA20DC2FA1CC228D3C2D8B538C2177C2921884C6B7F0D96F" + }, + { /* tv 22 */ + "NIST P-192", + "1618292094200346491064154703205151664562462359653015613567", + "74FEC215F253C6BD845831E059B318C87F727B136A700B91", + "4B702B15B126A703E7A7CEC3E0EC81F8DFCA73A59F5D88B9" + }, + { /* tv 23 */ + "NIST P-192", + "1484605055214526729816930749766694384906446681761906688", + "0C40230F9C4B8C0FD91F2C604FCBA9B87C2DFA153F010B4F", + "5FC4F5771F467971B2C82752413833A68CE00F4A9A692B02" + }, + { /* tv 24 */ + "NIST P-192", + "1569275434166462877105627261392580354519833538813866540831", + "28783BBF6208E1FF0F965FD8DC0C26FF1D8E02B433EDF2F7", + "A5852BBC44FD8164C1ABA9A3EC7A88E461D5D77ABD743E87" + }, + { /* tv 25 */ + "NIST P-192", + "3138550867681922400546388175470823984762234518836963313664", + "45DAF0A306121BDB3B82E734CB44FDF65C9930F0E4FD2068", + "F039FACE58EB7DE34E3374ADB28DF81F019C4548BAA75B64" + }, + { /* tv 26 */ + "NIST P-192", + "3138550119404545973088374812479323842475901485681169401600", + "1D5EC85004EA2ABA905CEF98A818A8C3516D7CB69A6FD575", + "4008F35F5820F66C902195644162E5AA231DD69C9E1ECC97" + }, + { /* tv 27 */ + "NIST P-192", + "24519928471166604179655321383971467003990211439919824896", + "F063727C2EA4D358AB02F6B0BEEB14DBEAF2E8A1DB3208EE", + "427418C015553361769B6A0C42923C4CA103740B6DCD9703" + }, + { /* tv 28 */ + "NIST P-192", + "46756768218837031708063422466358611246556475572231", + "DC81D33CA6604B1EFE49386CD492979EF807B8BAEB8566E3", + "D454247FF478514556333B3901C9F1CCC18DBC9AB938CFA0" + }, + { /* tv 29 */ + "NIST P-192", + "3138502977207688322901699644928655553044791844086883549215", + "D932741DF6AA0E1EED24279150436C752AA5ADCFD0698D72", + "9759B6D2EF21D885E94CDFF219F17004D8763401DAB021B5" + }, + { /* tv 30 */ + "NIST P-192", + "47890485652059026491391979477371914515865621847605503", + "571477E9D9F2A628780742257F7250C4224C483B30F3A97E", + "1AD35EE3177D22DD5F01B5A46FFDEC547B6A41786EBB8C8F" + }, + { /* tv 31 */ + "NIST P-192", + "3138549376958826959341570842566593375326996431013993775615", + "4C69939642792776C826DB8B4EBF4BD8C03FC9DFA2AEC822", + "29BF35BE52A6036E07EBA5741CFEB4C143310216EF1B9A2E" + }, + { /* tv 32 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284061", + "BB6F082321D34DBD786A1566915C6DD5EDF879AB0F5ADD67", + "6E1B2275883BACE37489210D1ACC64A046A2A26B8620B372" + }, + { /* tv 33 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284062", + "C0626BCF247DE5D307FD839238D72688774FC97A1CF8AD1B", + "63236628AC68C23E681ED88717D637FA13E594B18E055DF5" + }, + { /* tv 34 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284063", + "C1B4DB0227210613A6CA15C428024E40B6513365D72591A3", + "E1D94D79435E2F70B01707FED9820601887D13C13C0B80AC" + }, + { /* tv 35 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284064", + "44275CD2E1F46DC3F9F57636C2B4213B8BB445930510FF8A", + "10527CB7021CF37821BC79ED57E71671648959852DA2202F" + }, + { /* tv 36 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284065", + "B7310B4548FBFDBD29005092A5355BFCD99473733048AFDF", + "00615161232D83E1BD27A7A3BAB926B5E7BA3A99D630DD6F" + }, + { /* tv 37 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284066", + "8C9595E63B56B633BA3546B2B5414DE736DE4A9E7578B1E7", + "D99489D56CB0FF3E830C7866C55A9948528AC8322670384E" + }, + { /* tv 38 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284067", + "13B9310646EBC93B591746B3F7C64E05DEE08843DE1081C1", + "E123159C4BBEBD22EA0C4BD813BE5E12B045356A1E79194B" + }, + { /* tv 39 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284068", + "112AF141D33EFB9F2F68821E051E4EA004144A363C4A090A", + "91F341C403AD6C08D5D3E8D91F7E1F6080EF5F6BBCD4E3E1" + }, + { /* tv 40 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284069", + "1061343F3D456D0ECA013877F8C9E7B28FCCDCDA67EEB8AB", + "A5F9B355D1594FC86701071C185B79B697E153FDF4D8D6C0" + }, + { /* tv 41 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284070", + "1C995995EB76324F1844F7164D22B652280940370628A2AA", + "10E89A31C816148CFD60AA9BFF0588414CB3479EE55563FB" + }, + { /* tv 42 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284071", + "AA7C4F9EF99E3E96D1AEDE2BD9238842859BB150D1FE9D85", + "CDED5C9AB81239D6FE11C9A74D0B7A6A9F14A14DB6EC684F" + }, + { /* tv 43 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284072", + "818A4D308B1CABB74E9E8F2BA8D27C9E1D9D375AB980388F", + "FE2E55A1DF72783283D6D08344BA831FCF15ABDE893718C6" + }, + { /* tv 44 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284073", + "2FA1F92D1ECCE92014771993CC14899D4B5977883397EDDE", + "5CC7502108748DEBD8C474A687108CBF0D22757168C7093F" + }, + { /* tv 45 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284074", + "8DA75A1F75DDCD7660F923243060EDCE5DE37F007011FCFD", + "A834A030979F4CABE7DBF247024C3FE12B48FD069BF6004A" + }, + { /* tv 46 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284075", + "A37ABC6C431F9AC398BF5BD1AA6678320ACE8ECB93D23F2A", + "7AE4C3513666F7240128FBF5E44256F0F7E083A8EF43970F" + }, + { /* tv 47 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284076", + "10BB8E9840049B183E078D9C300E1605590118EBDD7FF590", + "CEC9EFF7B8906E84523607C919D89D40CED48DABC331515E" + }, + { /* tv 48 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284077", + "35433907297CC378B0015703374729D7A4FE46647084E4BA", + "5D9B667B0DECA3CFE15C534F88932B0DDAC764CEE24C41CD" + }, + { /* tv 49 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284078", + "76E32A2557599E6EDCD283201FB2B9AADFD0D359CBB263DA", + "87D3C81C8D45BADF559D1F012EDE2B600C4ABC99F302FA02" + }, + { /* tv 50 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284079", + "DAFEBF5828783F2AD35534631588A3F629A70FB16982A888", + "229425F266C25F05B94D8443EBE4796FA6CCE505A3816C54" + }, + { /* tv 51 */ + "NIST P-192", + "6277101735386680763835789423176059013767194773182842284080", + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", + "F8E6D46A003725879CEFEE1294DB32298C06885EE186B7EE" + }, + { /* tv 52 */ + "NIST P-224", + "1", + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34" + }, + { /* tv 53 */ + "NIST P-224", + "2", + "706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA6", + "1C2B76A7BC25E7702A704FA986892849FCA629487ACF3709D2E4E8BB" + }, + { /* tv 54 */ + "NIST P-224", + "3", + "DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D04", + "A3F7F03CADD0BE444C0AA56830130DDF77D317344E1AF3591981A925" + }, + { /* tv 55 */ + "NIST P-224", + "4", + "AE99FEEBB5D26945B54892092A8AEE02912930FA41CD114E40447301", + "0482580A0EC5BC47E88BC8C378632CD196CB3FA058A7114EB03054C9" + }, + { /* tv 56 */ + "NIST P-224", + "5", + "31C49AE75BCE7807CDFF22055D94EE9021FEDBB5AB51C57526F011AA", + "27E8BFF1745635EC5BA0C9F1C2EDE15414C6507D29FFE37E790A079B" + }, + { /* tv 57 */ + "NIST P-224", + "6", + "1F2483F82572251FCA975FEA40DB821DF8AD82A3C002EE6C57112408", + "89FAF0CCB750D99B553C574FAD7ECFB0438586EB3952AF5B4B153C7E" + }, + { /* tv 58 */ + "NIST P-224", + "7", + "DB2F6BE630E246A5CF7D99B85194B123D487E2D466B94B24A03C3E28", + "0F3A30085497F2F611EE2517B163EF8C53B715D18BB4E4808D02B963" + }, + { /* tv 59 */ + "NIST P-224", + "8", + "858E6F9CC6C12C31F5DF124AA77767B05C8BC021BD683D2B55571550", + "046DCD3EA5C43898C5C5FC4FDAC7DB39C2F02EBEE4E3541D1E78047A" + }, + { /* tv 60 */ + "NIST P-224", + "9", + "2FDCCCFEE720A77EF6CB3BFBB447F9383117E3DAA4A07E36ED15F78D", + "371732E4F41BF4F7883035E6A79FCEDC0E196EB07B48171697517463" + }, + { /* tv 61 */ + "NIST P-224", + "10", + "AEA9E17A306517EB89152AA7096D2C381EC813C51AA880E7BEE2C0FD", + "39BB30EAB337E0A521B6CBA1ABE4B2B3A3E524C14A3FE3EB116B655F" + }, + { /* tv 62 */ + "NIST P-224", + "11", + "EF53B6294ACA431F0F3C22DC82EB9050324F1D88D377E716448E507C", + "20B510004092E96636CFB7E32EFDED8265C266DFB754FA6D6491A6DA" + }, + { /* tv 63 */ + "NIST P-224", + "12", + "6E31EE1DC137F81B056752E4DEAB1443A481033E9B4C93A3044F4F7A", + "207DDDF0385BFDEAB6E9ACDA8DA06B3BBEF224A93AB1E9E036109D13" + }, + { /* tv 64 */ + "NIST P-224", + "13", + "34E8E17A430E43289793C383FAC9774247B40E9EBD3366981FCFAECA", + "252819F71C7FB7FBCB159BE337D37D3336D7FEB963724FDFB0ECB767" + }, + { /* tv 65 */ + "NIST P-224", + "14", + "A53640C83DC208603DED83E4ECF758F24C357D7CF48088B2CE01E9FA", + "D5814CD724199C4A5B974A43685FBF5B8BAC69459C9469BC8F23CCAF" + }, + { /* tv 66 */ + "NIST P-224", + "15", + "BAA4D8635511A7D288AEBEEDD12CE529FF102C91F97F867E21916BF9", + "979A5F4759F80F4FB4EC2E34F5566D595680A11735E7B61046127989" + }, + { /* tv 67 */ + "NIST P-224", + "16", + "0B6EC4FE1777382404EF679997BA8D1CC5CD8E85349259F590C4C66D", + "3399D464345906B11B00E363EF429221F2EC720D2F665D7DEAD5B482" + }, + { /* tv 68 */ + "NIST P-224", + "17", + "B8357C3A6CEEF288310E17B8BFEFF9200846CA8C1942497C484403BC", + "FF149EFA6606A6BD20EF7D1B06BD92F6904639DCE5174DB6CC554A26" + }, + { /* tv 69 */ + "NIST P-224", + "18", + "C9FF61B040874C0568479216824A15EAB1A838A797D189746226E4CC", + "EA98D60E5FFC9B8FCF999FAB1DF7E7EF7084F20DDB61BB045A6CE002" + }, + { /* tv 70 */ + "NIST P-224", + "19", + "A1E81C04F30CE201C7C9ACE785ED44CC33B455A022F2ACDBC6CAE83C", + "DCF1F6C3DB09C70ACC25391D492FE25B4A180BABD6CEA356C04719CD" + }, + { /* tv 71 */ + "NIST P-224", + "20", + "FCC7F2B45DF1CD5A3C0C0731CA47A8AF75CFB0347E8354EEFE782455", + "0D5D7110274CBA7CDEE90E1A8B0D394C376A5573DB6BE0BF2747F530" + }, + { /* tv 72 */ + "NIST P-224", + "112233445566778899", + "61F077C6F62ED802DAD7C2F38F5C67F2CC453601E61BD076BB46179E", + "2272F9E9F5933E70388EE652513443B5E289DD135DCC0D0299B225E4" + }, + { /* tv 73 */ + "NIST P-224", + "112233445566778899112233445566778899", + "029895F0AF496BFC62B6EF8D8A65C88C613949B03668AAB4F0429E35", + "3EA6E53F9A841F2019EC24BDE1A75677AA9B5902E61081C01064DE93" + }, + { /* tv 74 */ + "NIST P-224", + "6950511619965839450988900688150712778015737983940691968051900319680", + "AB689930BCAE4A4AA5F5CB085E823E8AE30FD365EB1DA4ABA9CF0379", + "3345A121BBD233548AF0D210654EB40BAB788A03666419BE6FBD34E7" + }, + { /* tv 75 */ + "NIST P-224", + "13479972933410060327035789020509431695094902435494295338570602119423", + "BDB6A8817C1F89DA1C2F3DD8E97FEB4494F2ED302A4CE2BC7F5F4025", + "4C7020D57C00411889462D77A5438BB4E97D177700BF7243A07F1680" + }, + { /* tv 76 */ + "NIST P-224", + "13479971751745682581351455311314208093898607229429740618390390702079", + "D58B61AA41C32DD5EBA462647DBA75C5D67C83606C0AF2BD928446A9", + "D24BA6A837BE0460DD107AE77725696D211446C5609B4595976B16BD" + }, + { /* tv 77 */ + "NIST P-224", + "13479972931865328106486971546324465392952975980343228160962702868479", + "DC9FA77978A005510980E929A1485F63716DF695D7A0C18BB518DF03", + "EDE2B016F2DDFFC2A8C015B134928275CE09E5661B7AB14CE0D1D403" + }, + { /* tv 78 */ + "NIST P-224", + "11795773708834916026404142434151065506931607341523388140225443265536", + "499D8B2829CFB879C901F7D85D357045EDAB55028824D0F05BA279BA", + "BF929537B06E4015919639D94F57838FA33FC3D952598DCDBB44D638" + }, + { /* tv 79 */ + "NIST P-224", + "784254593043826236572847595991346435467177662189391577090", + "8246C999137186632C5F9EDDF3B1B0E1764C5E8BD0E0D8A554B9CB77", + "E80ED8660BC1CB17AC7D845BE40A7A022D3306F116AE9F81FEA65947" + }, + { /* tv 80 */ + "NIST P-224", + "13479767645505654746623887797783387853576174193480695826442858012671", + "6670C20AFCCEAEA672C97F75E2E9DD5C8460E54BB38538EBB4BD30EB", + "F280D8008D07A4CAF54271F993527D46FF3FF46FD1190A3F1FAA4F74" + }, + { /* tv 81 */ + "NIST P-224", + "205688069665150753842126177372015544874550518966168735589597183", + "000ECA934247425CFD949B795CB5CE1EFF401550386E28D1A4C5A8EB", + "D4C01040DBA19628931BC8855370317C722CBD9CA6156985F1C2E9CE" + }, + { /* tv 82 */ + "NIST P-224", + "13479966930919337728895168462090683249159702977113823384618282123295", + "EF353BF5C73CD551B96D596FBC9A67F16D61DD9FE56AF19DE1FBA9CD", + "21771B9CDCE3E8430C09B3838BE70B48C21E15BC09EE1F2D7945B91F" + }, + { /* tv 83 */ + "NIST P-224", + "50210731791415612487756441341851895584393717453129007497216", + "4036052A3091EB481046AD3289C95D3AC905CA0023DE2C03ECD451CF", + "D768165A38A2B96F812586A9D59D4136035D9C853A5BF2E1C86A4993" + }, + { /* tv 84 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368041", + "FCC7F2B45DF1CD5A3C0C0731CA47A8AF75CFB0347E8354EEFE782455", + "F2A28EEFD8B345832116F1E574F2C6B2C895AA8C24941F40D8B80AD1" + }, + { /* tv 85 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368042", + "A1E81C04F30CE201C7C9ACE785ED44CC33B455A022F2ACDBC6CAE83C", + "230E093C24F638F533DAC6E2B6D01DA3B5E7F45429315CA93FB8E634" + }, + { /* tv 86 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368043", + "C9FF61B040874C0568479216824A15EAB1A838A797D189746226E4CC", + "156729F1A003647030666054E208180F8F7B0DF2249E44FBA5931FFF" + }, + { /* tv 87 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368044", + "B8357C3A6CEEF288310E17B8BFEFF9200846CA8C1942497C484403BC", + "00EB610599F95942DF1082E4F9426D086FB9C6231AE8B24933AAB5DB" + }, + { /* tv 88 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368045", + "0B6EC4FE1777382404EF679997BA8D1CC5CD8E85349259F590C4C66D", + "CC662B9BCBA6F94EE4FF1C9C10BD6DDD0D138DF2D099A282152A4B7F" + }, + { /* tv 89 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368046", + "BAA4D8635511A7D288AEBEEDD12CE529FF102C91F97F867E21916BF9", + "6865A0B8A607F0B04B13D1CB0AA992A5A97F5EE8CA1849EFB9ED8678" + }, + { /* tv 90 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368047", + "A53640C83DC208603DED83E4ECF758F24C357D7CF48088B2CE01E9FA", + "2A7EB328DBE663B5A468B5BC97A040A3745396BA636B964370DC3352" + }, + { /* tv 91 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368048", + "34E8E17A430E43289793C383FAC9774247B40E9EBD3366981FCFAECA", + "DAD7E608E380480434EA641CC82C82CBC92801469C8DB0204F13489A" + }, + { /* tv 92 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368049", + "6E31EE1DC137F81B056752E4DEAB1443A481033E9B4C93A3044F4F7A", + "DF82220FC7A4021549165325725F94C3410DDB56C54E161FC9EF62EE" + }, + { /* tv 93 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368050", + "EF53B6294ACA431F0F3C22DC82EB9050324F1D88D377E716448E507C", + "DF4AEFFFBF6D1699C930481CD102127C9A3D992048AB05929B6E5927" + }, + { /* tv 94 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368051", + "AEA9E17A306517EB89152AA7096D2C381EC813C51AA880E7BEE2C0FD", + "C644CF154CC81F5ADE49345E541B4D4B5C1ADB3EB5C01C14EE949AA2" + }, + { /* tv 95 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368052", + "2FDCCCFEE720A77EF6CB3BFBB447F9383117E3DAA4A07E36ED15F78D", + "C8E8CD1B0BE40B0877CFCA1958603122F1E6914F84B7E8E968AE8B9E" + }, + { /* tv 96 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368053", + "858E6F9CC6C12C31F5DF124AA77767B05C8BC021BD683D2B55571550", + "FB9232C15A3BC7673A3A03B0253824C53D0FD1411B1CABE2E187FB87" + }, + { /* tv 97 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368054", + "DB2F6BE630E246A5CF7D99B85194B123D487E2D466B94B24A03C3E28", + "F0C5CFF7AB680D09EE11DAE84E9C1072AC48EA2E744B1B7F72FD469E" + }, + { /* tv 98 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368055", + "1F2483F82572251FCA975FEA40DB821DF8AD82A3C002EE6C57112408", + "76050F3348AF2664AAC3A8B05281304EBC7A7914C6AD50A4B4EAC383" + }, + { /* tv 99 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368056", + "31C49AE75BCE7807CDFF22055D94EE9021FEDBB5AB51C57526F011AA", + "D817400E8BA9CA13A45F360E3D121EAAEB39AF82D6001C8186F5F866" + }, + { /* tv 100 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368057", + "AE99FEEBB5D26945B54892092A8AEE02912930FA41CD114E40447301", + "FB7DA7F5F13A43B81774373C879CD32D6934C05FA758EEB14FCFAB38" + }, + { /* tv 101 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368058", + "DF1B1D66A551D0D31EFF822558B9D2CC75C2180279FE0D08FD896D04", + "5C080FC3522F41BBB3F55A97CFECF21F882CE8CBB1E50CA6E67E56DC" + }, + { /* tv 102 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368059", + "706A46DC76DCB76798E60E6D89474788D16DC18032D268FD1A704FA6", + "E3D4895843DA188FD58FB0567976D7B50359D6B78530C8F62D1B1746" + }, + { /* tv 103 */ + "NIST P-224", + "26959946667150639794667015087019625940457807714424391721682722368060", + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", + "42C89C774A08DC04B3DD201932BC8A5EA5F8B89BBB2A7E667AFF81CD" + }, + { /* tv 104 */ + "NIST P-256", + "1", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5" + }, + { /* tv 105 */ + "NIST P-256", + "2", + "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978", + "07775510DB8ED040293D9AC69F7430DBBA7DADE63CE982299E04B79D227873D1" + }, + { /* tv 106 */ + "NIST P-256", + "3", + "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C", + "8734640C4998FF7E374B06CE1A64A2ECD82AB036384FB83D9A79B127A27D5032" + }, + { /* tv 107 */ + "NIST P-256", + "4", + "E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B030852", + "E0F1575A4C633CC719DFEE5FDA862D764EFC96C3F30EE0055C42C23F184ED8C6" + }, + { /* tv 108 */ + "NIST P-256", + "5", + "51590B7A515140D2D784C85608668FDFEF8C82FD1F5BE52421554A0DC3D033ED", + "E0C17DA8904A727D8AE1BF36BF8A79260D012F00D4D80888D1D0BB44FDA16DA4" + }, + { /* tv 109 */ + "NIST P-256", + "6", + "B01A172A76A4602C92D3242CB897DDE3024C740DEBB215B4C6B0AAE93C2291A9", + "E85C10743237DAD56FEC0E2DFBA703791C00F7701C7E16BDFD7C48538FC77FE2" + }, + { /* tv 110 */ + "NIST P-256", + "7", + "8E533B6FA0BF7B4625BB30667C01FB607EF9F8B8A80FEF5B300628703187B2A3", + "73EB1DBDE03318366D069F83A6F5900053C73633CB041B21C55E1A86C1F400B4" + }, + { /* tv 111 */ + "NIST P-256", + "8", + "62D9779DBEE9B0534042742D3AB54CADC1D238980FCE97DBB4DD9DC1DB6FB393", + "AD5ACCBD91E9D8244FF15D771167CEE0A2ED51F6BBE76A78DA540A6A0F09957E" + }, + { /* tv 112 */ + "NIST P-256", + "9", + "EA68D7B6FEDF0B71878938D51D71F8729E0ACB8C2C6DF8B3D79E8A4B90949EE0", + "2A2744C972C9FCE787014A964A8EA0C84D714FEAA4DE823FE85A224A4DD048FA" + }, + { /* tv 113 */ + "NIST P-256", + "10", + "CEF66D6B2A3A993E591214D1EA223FB545CA6C471C48306E4C36069404C5723F", + "878662A229AAAE906E123CDD9D3B4C10590DED29FE751EEECA34BBAA44AF0773" + }, + { /* tv 114 */ + "NIST P-256", + "11", + "3ED113B7883B4C590638379DB0C21CDA16742ED0255048BF433391D374BC21D1", + "9099209ACCC4C8A224C843AFA4F4C68A090D04DA5E9889DAE2F8EEFCE82A3740" + }, + { /* tv 115 */ + "NIST P-256", + "12", + "741DD5BDA817D95E4626537320E5D55179983028B2F82C99D500C5EE8624E3C4", + "0770B46A9C385FDC567383554887B1548EEB912C35BA5CA71995FF22CD4481D3" + }, + { /* tv 116 */ + "NIST P-256", + "13", + "177C837AE0AC495A61805DF2D85EE2FC792E284B65EAD58A98E15D9D46072C01", + "63BB58CD4EBEA558A24091ADB40F4E7226EE14C3A1FB4DF39C43BBE2EFC7BFD8" + }, + { /* tv 117 */ + "NIST P-256", + "14", + "54E77A001C3862B97A76647F4336DF3CF126ACBE7A069C5E5709277324D2920B", + "F599F1BB29F4317542121F8C05A2E7C37171EA77735090081BA7C82F60D0B375" + }, + { /* tv 118 */ + "NIST P-256", + "15", + "F0454DC6971ABAE7ADFB378999888265AE03AF92DE3A0EF163668C63E59B9D5F", + "B5B93EE3592E2D1F4E6594E51F9643E62A3B21CE75B5FA3F47E59CDE0D034F36" + }, + { /* tv 119 */ + "NIST P-256", + "16", + "76A94D138A6B41858B821C629836315FCD28392EFF6CA038A5EB4787E1277C6E", + "A985FE61341F260E6CB0A1B5E11E87208599A0040FC78BAA0E9DDD724B8C5110" + }, + { /* tv 120 */ + "NIST P-256", + "17", + "47776904C0F1CC3A9C0984B66F75301A5FA68678F0D64AF8BA1ABCE34738A73E", + "AA005EE6B5B957286231856577648E8381B2804428D5733F32F787FF71F1FCDC" + }, + { /* tv 121 */ + "NIST P-256", + "18", + "1057E0AB5780F470DEFC9378D1C7C87437BB4C6F9EA55C63D936266DBD781FDA", + "F6F1645A15CBE5DC9FA9B7DFD96EE5A7DCC11B5C5EF4F1F78D83B3393C6A45A2" + }, + { /* tv 122 */ + "NIST P-256", + "19", + "CB6D2861102C0C25CE39B7C17108C507782C452257884895C1FC7B74AB03ED83", + "58D7614B24D9EF515C35E7100D6D6CE4A496716E30FA3E03E39150752BCECDAA" + }, + { /* tv 123 */ + "NIST P-256", + "20", + "83A01A9378395BAB9BCD6A0AD03CC56D56E6B19250465A94A234DC4C6B28DA9A", + "76E49B6DE2F73234AE6A5EB9D612B75C9F2202BB6923F54FF8240AAA86F640B8" + }, + { /* tv 124 */ + "NIST P-256", + "112233445566778899", + "339150844EC15234807FE862A86BE77977DBFB3AE3D96F4C22795513AEAAB82F", + "B1C14DDFDC8EC1B2583F51E85A5EB3A155840F2034730E9B5ADA38B674336A21" + }, + { /* tv 125 */ + "NIST P-256", + "112233445566778899112233445566778899", + "1B7E046A076CC25E6D7FA5003F6729F665CC3241B5ADAB12B498CD32F2803264", + "BFEA79BE2B666B073DB69A2A241ADAB0738FE9D2DD28B5604EB8C8CF097C457B" + }, + { /* tv 126 */ + "NIST P-256", + "29852220098221261079183923314599206100666902414330245206392788703677" + "545185283", + "9EACE8F4B071E677C5350B02F2BB2B384AAE89D58AA72CA97A170572E0FB222F", + "1BBDAEC2430B09B93F7CB08678636CE12EAAFD58390699B5FD2F6E1188FC2A78" + }, + { /* tv 127 */ + "NIST P-256", + "57896042899961394862005778464643882389978449576758748073725983489954" + "366354431", + "878F22CC6DB6048D2B767268F22FFAD8E56AB8E2DC615F7BD89F1E350500DD8D", + "714A5D7BB901C9C5853400D12341A892EF45D87FC553786756C4F0C9391D763E" + }, + { /* tv 128 */ + "NIST P-256", + "17668453929457101515018891057290498829976600048248489159554196603666" + "36031", + "659A379625AB122F2512B8DADA02C6348D53B54452DFF67AC7ACE4E8856295CA", + "49D81AB97B648464D0B4A288BD7818FAB41A16426E943527C4FED8736C53D0F6" + }, + { /* tv 129 */ + "NIST P-256", + "28948025760307534517734791687894775804466072615242963443097661355606" + "862201087", + "CBCEAAA8A4DD44BBCE58E8DB7740A5510EC2CB7EA8DA8D8F036B3FB04CDA4DE4", + "4BD7AA301A80D7F59FD983FEDBE59BB7B2863FE46494935E3745B360E32332FA" + }, + { /* tv 130 */ + "NIST P-256", + "11307821046087054894481169596029064497322922462583843642447709583464" + "5696384", + "F0C4A0576154FF3A33A3460D42EAED806E854DFA37125221D37935124BA462A4", + "5B392FA964434D29EEC6C9DBC261CF116796864AA2FAADB984A2DF38D1AEF7A3" + }, + { /* tv 131 */ + "NIST P-256", + "12078056106883488161242983286051341125085761470677906721917479268909" + "056", + "5E6C8524B6369530B12C62D31EC53E0288173BD662BDF680B53A41ECBCAD00CC", + "447FE742C2BFEF4D0DB14B5B83A2682309B5618E0064A94804E9282179FE089F" + }, + { /* tv 132 */ + "NIST P-256", + "57782969857385448082319957860328652998540760998293976083718804450708" + "503920639", + "03792E541BC209076A3D7920A915021ECD396A6EB5C3960024BE5575F3223484", + "FC774AE092403101563B712F68170312304F20C80B40C06282063DB25F268DE4" + }, + { /* tv 133 */ + "NIST P-256", + "57896017119460046759583662757090100341435943767777707906455551163257" + "755533312", + "2379FF85AB693CDF901D6CE6F2473F39C04A2FE3DCD842CE7AAB0E002095BCF8", + "F8B476530A634589D5129E46F322B02FBC610A703D80875EE70D7CE1877436A1" + }, + { /* tv 134 */ + "NIST P-256", + "45231284837428728468128217101764741272643368423846421299930586483716" + "0993279", + "C1E4072C529BF2F44DA769EFC934472848003B3AF2C0F5AA8F8DDBD53E12ED7C", + "39A6EE77812BB37E8079CD01ED649D3830FCA46F718C1D3993E4A591824ABCDB" + }, + { /* tv 135 */ + "NIST P-256", + "90457133917406513429363440794605400077474605586691772987667636755846" + "9746684", + "34DFBC09404C21E250A9B40FA8772897AC63A094877DB65862B61BD1507B34F3", + "CF6F8A876C6F99CEAEC87148F18C7E1E0DA6E165FFC8ED82ABB65955215F77D3" + }, + { /* tv 136 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044349", + "83A01A9378395BAB9BCD6A0AD03CC56D56E6B19250465A94A234DC4C6B28DA9A", + "891B64911D08CDCC5195A14629ED48A360DDFD4596DC0AB007DBF5557909BF47" + }, + { /* tv 137 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044350", + "CB6D2861102C0C25CE39B7C17108C507782C452257884895C1FC7B74AB03ED83", + "A7289EB3DB2610AFA3CA18EFF292931B5B698E92CF05C1FC1C6EAF8AD4313255" + }, + { /* tv 138 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044351", + "1057E0AB5780F470DEFC9378D1C7C87437BB4C6F9EA55C63D936266DBD781FDA", + "090E9BA4EA341A246056482026911A58233EE4A4A10B0E08727C4CC6C395BA5D" + }, + { /* tv 139 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044352", + "47776904C0F1CC3A9C0984B66F75301A5FA68678F0D64AF8BA1ABCE34738A73E", + "55FFA1184A46A8D89DCE7A9A889B717C7E4D7FBCD72A8CC0CD0878008E0E0323" + }, + { /* tv 140 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044353", + "76A94D138A6B41858B821C629836315FCD28392EFF6CA038A5EB4787E1277C6E", + "567A019DCBE0D9F2934F5E4A1EE178DF7A665FFCF0387455F162228DB473AEEF" + }, + { /* tv 141 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044354", + "F0454DC6971ABAE7ADFB378999888265AE03AF92DE3A0EF163668C63E59B9D5F", + "4A46C11BA6D1D2E1B19A6B1AE069BC19D5C4DE328A4A05C0B81A6321F2FCB0C9" + }, + { /* tv 142 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044355", + "54E77A001C3862B97A76647F4336DF3CF126ACBE7A069C5E5709277324D2920B", + "0A660E43D60BCE8BBDEDE073FA5D183C8E8E15898CAF6FF7E45837D09F2F4C8A" + }, + { /* tv 143 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044356", + "177C837AE0AC495A61805DF2D85EE2FC792E284B65EAD58A98E15D9D46072C01", + "9C44A731B1415AA85DBF6E524BF0B18DD911EB3D5E04B20C63BC441D10384027" + }, + { /* tv 144 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044357", + "741DD5BDA817D95E4626537320E5D55179983028B2F82C99D500C5EE8624E3C4", + "F88F4B9463C7A024A98C7CAAB7784EAB71146ED4CA45A358E66A00DD32BB7E2C" + }, + { /* tv 145 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044358", + "3ED113B7883B4C590638379DB0C21CDA16742ED0255048BF433391D374BC21D1", + "6F66DF64333B375EDB37BC505B0B3975F6F2FB26A16776251D07110317D5C8BF" + }, + { /* tv 146 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044359", + "CEF66D6B2A3A993E591214D1EA223FB545CA6C471C48306E4C36069404C5723F", + "78799D5CD655517091EDC32262C4B3EFA6F212D7018AE11135CB4455BB50F88C" + }, + { /* tv 147 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044360", + "EA68D7B6FEDF0B71878938D51D71F8729E0ACB8C2C6DF8B3D79E8A4B90949EE0", + "D5D8BB358D36031978FEB569B5715F37B28EB0165B217DC017A5DDB5B22FB705" + }, + { /* tv 148 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044361", + "62D9779DBEE9B0534042742D3AB54CADC1D238980FCE97DBB4DD9DC1DB6FB393", + "52A533416E1627DCB00EA288EE98311F5D12AE0A4418958725ABF595F0F66A81" + }, + { /* tv 149 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044362", + "8E533B6FA0BF7B4625BB30667C01FB607EF9F8B8A80FEF5B300628703187B2A3", + "8C14E2411FCCE7CA92F9607C590A6FFFAC38C9CD34FBE4DE3AA1E5793E0BFF4B" + }, + { /* tv 150 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044363", + "B01A172A76A4602C92D3242CB897DDE3024C740DEBB215B4C6B0AAE93C2291A9", + "17A3EF8ACDC8252B9013F1D20458FC86E3FF0890E381E9420283B7AC7038801D" + }, + { /* tv 151 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044364", + "51590B7A515140D2D784C85608668FDFEF8C82FD1F5BE52421554A0DC3D033ED", + "1F3E82566FB58D83751E40C9407586D9F2FED1002B27F7772E2F44BB025E925B" + }, + { /* tv 152 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044365", + "E2534A3532D08FBBA02DDE659EE62BD0031FE2DB785596EF509302446B030852", + "1F0EA8A4B39CC339E62011A02579D289B103693D0CF11FFAA3BD3DC0E7B12739" + }, + { /* tv 153 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044366", + "5ECBE4D1A6330A44C8F7EF951D4BF165E6C6B721EFADA985FB41661BC6E7FD6C", + "78CB9BF2B6670082C8B4F931E59B5D1327D54FCAC7B047C265864ED85D82AFCD" + }, + { /* tv 154 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044367", + "7CF27B188D034F7E8A52380304B51AC3C08969E277F21B35A60B48FC47669978", + "F888AAEE24712FC0D6C26539608BCF244582521AC3167DD661FB4862DD878C2E" + }, + { /* tv 155 */ + "NIST P-256", + "11579208921035624876269744694940757352999695522413576034242225906106" + "8512044368", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + "B01CBD1C01E58065711814B583F061E9D431CCA994CEA1313449BF97C840AE0A" + }, + { /* tv 156 */ + "NIST P-384", + "1", + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502" + "F25DBF55296C3A545E3872760AB7", + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60" + "B1CE1D7E819D7A431D7C90EA0E5F" + }, + { /* tv 157 */ + "NIST P-384", + "2", + "08D999057BA3D2D969260045C55B97F089025959A6F434D651D207D19FB96E9E4FE0" + "E86EBE0E64F85B96A9C75295DF61", + "8E80F1FA5B1B3CEDB7BFE8DFFD6DBA74B275D875BC6CC43E904E505F256AB4255FFD" + "43E94D39E22D61501E700A940E80" + }, + { /* tv 158 */ + "NIST P-384", + "3", + "077A41D4606FFA1464793C7E5FDC7D98CB9D3910202DCD06BEA4F240D3566DA6B408" + "BBAE5026580D02D7E5C70500C831", + "C995F7CA0B0C42837D0BBE9602A9FC998520B41C85115AA5F7684C0EDC111EACC24A" + "BD6BE4B5D298B65F28600A2F1DF1" + }, + { /* tv 159 */ + "NIST P-384", + "4", + "138251CD52AC9298C1C8AAD977321DEB97E709BD0B4CA0ACA55DC8AD51DCFC9D1589" + "A1597E3A5120E1EFD631C63E1835", + "CACAE29869A62E1631E8A28181AB56616DC45D918ABC09F3AB0E63CF792AA4DCED73" + "87BE37BBA569549F1C02B270ED67" + }, + { /* tv 160 */ + "NIST P-384", + "5", + "11DE24A2C251C777573CAC5EA025E467F208E51DBFF98FC54F6661CBE56583B03788" + "2F4A1CA297E60ABCDBC3836D84BC", + "8FA696C77440F92D0F5837E90A00E7C5284B447754D5DEE88C986533B6901AEB3177" + "686D0AE8FB33184414ABE6C1713A" + }, + { /* tv 161 */ + "NIST P-384", + "6", + "627BE1ACD064D2B2226FE0D26F2D15D3C33EBCBB7F0F5DA51CBD41F2625738302131" + "7D7202FF30E50937F0854E35C5DF", + "09766A4CB3F8B1C21BE6DDA6C14F1575B2C95352644F774C99864F613715441604C4" + "5B8D84E165311733A408D3F0F934" + }, + { /* tv 162 */ + "NIST P-384", + "7", + "283C1D7365CE4788F29F8EBF234EDFFEAD6FE997FBEA5FFA2D58CC9DFA7B1C508B05" + "526F55B9EBB2040F05B48FB6D0E1", + "9475C99061E41B88BA52EFDB8C1690471A61D867ED799729D9C92CD01DBD225630D8" + "4EDE32A78F9E64664CDAC512EF8C" + }, + { /* tv 163 */ + "NIST P-384", + "8", + "1692778EA596E0BE75114297A6FA383445BF227FBE58190A900C3C73256F11FB5A32" + "58D6F403D5ECE6E9B269D822C87D", + "DCD2365700D4106A835388BA3DB8FD0E22554ADC6D521CD4BD1C30C2EC0EEC196BAD" + "E1E9CDD1708D6F6ABFA4022B0AD2" + }, + { /* tv 164 */ + "NIST P-384", + "9", + "8F0A39A4049BCB3EF1BF29B8B025B78F2216F7291E6FD3BAC6CB1EE285FB6E21C388" + "528BFEE2B9535C55E4461079118B", + "62C77E1438B601D6452C4A5322C3A9799A9B3D7CA3C400C6B7678854AED9B3029E74" + "3EFEDFD51B68262DA4F9AC664AF8" + }, + { /* tv 165 */ + "NIST P-384", + "10", + "A669C5563BD67EEC678D29D6EF4FDE864F372D90B79B9E88931D5C29291238CCED8E" + "85AB507BF91AA9CB2D13186658FB", + "A988B72AE7C1279F22D9083DB5F0ECDDF70119550C183C31C502DF78C3B705A8296D" + "8195248288D997784F6AB73A21DD" + }, + { /* tv 166 */ + "NIST P-384", + "11", + "099056E27DA7B998DA1EEEC2904816C57FE935ED5837C37456C9FD14892D3F8C4749" + "B66E3AFB81D626356F3B55B4DDD8", + "2E4C0C234E30AB96688505544AC5E0396FC4EED8DFC363FD43FF93F41B52A3255466" + "D51263AAFF357D5DBA8138C5E0BB" + }, + { /* tv 167 */ + "NIST P-384", + "12", + "952A7A349BD49289AB3AC421DCF683D08C2ED5E41F6D0E21648AF2691A481406DA4A" + "5E22DA817CB466DA2EA77D2A7022", + "A0320FAF84B5BC0563052DEAE6F66F2E09FB8036CE18A0EBB9028B096196B50D031A" + "A64589743E229EF6BACCE21BD16E" + }, + { /* tv 168 */ + "NIST P-384", + "13", + "A567BA97B67AEA5BAFDAF5002FFCC6AB9632BFF9F01F873F6267BCD1F0F11C139EE5" + "F441ABD99F1BAAF1CA1E3B5CBCE7", + "DE1B38B3989F3318644E4147AF164ECC5185595046932EC086329BE057857D66776B" + "CB8272218A7D6423A12736F429CC" + }, + { /* tv 169 */ + "NIST P-384", + "14", + "E8C8F94D44FBC2396BBEAC481B89D2B0877B1DFFD23E7DC95DE541EB651CCA2C41AB" + "A24DBC02DE6637209ACCF0F59EA0", + "891AE44356FC8AE0932BCBF6DE52C8A933B86191E7728D79C8319413A09D0F48FC46" + "8BA05509DE22D7EE5C9E1B67B888" + }, + { /* tv 170 */ + "NIST P-384", + "15", + "B3D13FC8B32B01058CC15C11D813525522A94156FFF01C205B21F9F7DA7C4E9CA849" + "557A10B6383B4B88701A9606860B", + "152919E7DF9162A61B049B2536164B1BEEBAC4A11D749AF484D1114373DFBFD9838D" + "24F8B284AF50985D588D33F7BD62" + }, + { /* tv 171 */ + "NIST P-384", + "16", + "D5D89C3B5282369C5FBD88E2B231511A6B80DFF0E5152CF6A464FA9428A8583BAC8E" + "BC773D157811A462B892401DAFCF", + "D815229DE12906D241816D5E9A9448F1D41D4FC40E2A3BDB9CABA57E440A7ABAD121" + "0CB8F49BF2236822B755EBAB3673" + }, + { /* tv 172 */ + "NIST P-384", + "17", + "4099952208B4889600A5EBBCB13E1A32692BEFB0733B41E6DCC614E42E5805F81701" + "2A991AF1F486CAF3A9ADD9FFCC03", + "5ECF94777833059839474594AF603598163AD3F8008AD0CD9B797D277F2388B304DA" + "4D2FAA9680ECFA650EF5E23B09A0" + }, + { /* tv 173 */ + "NIST P-384", + "18", + "DFB1FE3A40F7AC9B64C41D39360A7423828B97CB088A4903315E402A7089FA0F8B6C" + "2355169CC9C99DFB44692A9B93DD", + "453ACA1243B5EC6B423A68A25587E1613A634C1C42D2EE7E6C57F449A1C91DC89168" + "B7036EC0A7F37A366185233EC522" + }, + { /* tv 174 */ + "NIST P-384", + "19", + "8D481DAB912BC8AB16858A211D750B77E07DBECCA86CD9B012390B430467AABF59C8" + "651060801C0E9599E68713F5D41B", + "A1592FF0121460857BE99F2A60669050B2291B68A1039AA0594B32FD7ADC0E8C11FF" + "BA5608004E646995B07E75E52245" + }, + { /* tv 175 */ + "NIST P-384", + "20", + "605508EC02C534BCEEE9484C86086D2139849E2B11C1A9CA1E2808DEC2EAF161AC8A" + "105D70D4F85C50599BE5800A623F", + "5158EE87962AC6B81F00A103B8543A07381B7639A3A65F1353AEF11B733106DDE92E" + "99B78DE367B48E238C38DAD8EEDD" + }, + { /* tv 176 */ + "NIST P-384", + "112233445566778899", + "A499EFE48839BC3ABCD1C5CEDBDD51904F9514DB44F4686DB918983B0C9DC3AEE05A" + "88B72433E9515F91A329F5F4FA60", + "3B7CA28EF31F809C2F1BA24AAED847D0F8B406A4B8968542DE139DB5828CA410E615" + "D1182E25B91B1131E230B727D36A" + }, + { /* tv 177 */ + "NIST P-384", + "112233445566778899112233445566778899", + "90A0B1CAC601676B083F21E07BC7090A3390FE1B9C7F61D842D27FA315FB38D83667" + "A11A71438773E483F2A114836B24", + "3197D3C6123F0D6CD65D5F0DE106FEF36656CB16DC7CD1A6817EB1D51510135A8F49" + "2F72665CFD1053F75ED03A7D04C9" + }, + { /* tv 178 */ + "NIST P-384", + "10158184112867540819754776755819761756724522948540419979637868435924" + "061464745859402573149498125806098880003248619520", + "F2A066BD332DC59BBC3D01DA1B124C687D8BB44611186422DE94C1DA4ECF150E664D" + "353CCDB5CB2652685F8EB4D2CD49", + "D6ED0BF75FDD8E53D87765FA746835B673881D6D1907163A2C43990D75B454294F94" + "2EC571AD5AAE1806CAF2BB8E9A4A" + }, + { /* tv 179 */ + "NIST P-384", + "98505015511059910282450526050569921398100949089127992541158476838813" + "57749738726091734403950439157209401153690566655", + "5C7F9845D1C4AA44747F9137B6F9C39B36B26B8A62E8AF97290434D5F3B214F5A013" + "1550ADB19058DC4C8780C4165C4A", + "712F7FCCC86F647E70DB8798228CB16344AF3D00B139B6F8502939C2A965AF0EB4E3" + "9E2E16AB8F597B8D5630A50C9D85" + }, + { /* tv 180 */ + "NIST P-384", + "98505027234057470973172711947633104824627514551856996305716616579463" + "08788426092983270628740691202018691293898608608", + "DD5838F7EC3B8ACF1BECFD746F8B668C577107E93548ED93ED0D254C112E76B10F05" + "3109EF8428BFCD50D38C4C030C57", + "33244F479CDAC34F160D9E4CE2D19D2FF0E3305B5BF0EEF29E91E9DE6E28F678C61B" + "773AA7E3C03740E1A49D1AA2493C" + }, + { /* tv 181 */ + "NIST P-384", + "11461893718178329909476114004508894060702157352553702808117365878450" + "16396640969656447803207438173695115264", + "CB8ED893530BFBA04B4CA655923AAAD109A62BC8411D5925316C32D33602459C3305" + "7A1FBCB5F70AEB295D90F9165FBC", + "426AEE3E91B08420F9B357B66D5AFCBCF3956590BF5564DBF9086042EB880493D19D" + "A39AAA6436C6B5FC66CE5596B43F" + }, + { /* tv 182 */ + "NIST P-384", + "96193414382170976418653902971897088589380179864261526226395001797746" + "24579127744608993294698873437325090751520764", + "67F714012B6B070182122DDD435CC1C2262A1AB88939BC6A2906CB2B4137C5E82B45" + "82160F6403CAB887ACDF5786A268", + "90E31CF398CE2F8C5897C7380BF541075D1B4D3CB70547262B7095731252F181AC05" + "97C66AF8311C7780DB39DEC0BD32" + }, + { /* tv 183 */ + "NIST P-384", + "12313079966238337423874003523801725660779274151368132827356419183955" + "85376659282194317590461518639141730493780722175", + "55A79DF7B53A99D31462C7E1A5ED5623970715BB1021098CB973A7520CBD6365E613" + "E4B2467486FB37E86E01CEE09B8F", + "B95AEB71693189911661B709A886A1867F056A0EFE401EE11C06030E46F7A87731DA" + "4575863178012208707DD666727C" + }, + { /* tv 184 */ + "NIST P-384", + "58711883885468380094290672250481034308669902145190694600327412897305" + "8942197377013128840514404789143516741631", + "9539A968CF819A0E52E10EEA3BACA1B6480D7E4DF69BC07002C568569047110EE4FE" + "72FCA423FDD5179D6E0E19C44844", + "A7728F37A0AE0DF2716061900D83A4DA149144129F89A214A8260464BAB609BB322E" + "4E67DE5E4C4C6CB8D25983EC19B0" + }, + { /* tv 185 */ + "NIST P-384", + "15391407753067173966379507087689476645146601937464415054145255714789" + "0542143280855693795882295846834387672681660416", + "933FC13276672AB360D909161CD02D830B1628935DF0D800C6ED602C59D575A86A8A" + "97E3A2D697E3ED06BE741C0097D6", + "F35296BD7A6B4C6C025ED6D84338CCCC7522A45C5D4FBDB1442556CAEFB598128FA1" + "88793ADA510EB5F44E90A4E4BEF1" + }, + { /* tv 186 */ + "NIST P-384", + "75148784606135150476268171850082176256856776750560539466196504390587" + "921789283134009866871754361028131485122560", + "0CE31E1C4A937071E6EBACA026A93D783848BCC0C1585DAF639518125FCD1F1629D6" + "3041ABFB11FFC8F03FA8B6FCF6BF", + "A69EA55BE4BEAB2D5224050FEBFFBDFCFD614624C3B4F228909EB80012F003756D1C" + "377E52F04FA539237F24DD080E2E" + }, + { /* tv 187 */ + "NIST P-384", + "19691383761310193665095292424754807745686799029814707849273381514021" + "788371252213000473497648851202400395528761229312", + "6842CFE3589AC268818291F31D44177A9168DCBC19F321ED66D81ECF59E31B54CCA0" + "DDFD4C4136780171748D69A91C54", + "E3A5ECD5AC725F13DBC631F358C6E817EDCF3A613B83832741A9DB591A0BAE767FC7" + "14F70C2E7EA891E4312047DECCC0" + }, + { /* tv 188 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942623", + "605508EC02C534BCEEE9484C86086D2139849E2B11C1A9CA1E2808DEC2EAF161AC8A" + "105D70D4F85C50599BE5800A623F", + "AEA7117869D53947E0FF5EFC47ABC5F8C7E489C65C59A0ECAC510EE48CCEF92116D1" + "6647721C984B71DC73C825271122" + }, + { /* tv 189 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942624", + "8D481DAB912BC8AB16858A211D750B77E07DBECCA86CD9B012390B430467AABF59C8" + "651060801C0E9599E68713F5D41B", + "5EA6D00FEDEB9F7A841660D59F996FAF4DD6E4975EFC655FA6B4CD028523F172EE00" + "45A8F7FFB19B966A4F828A1ADDBA" + }, + { /* tv 190 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942625", + "DFB1FE3A40F7AC9B64C41D39360A7423828B97CB088A4903315E402A7089FA0F8B6C" + "2355169CC9C99DFB44692A9B93DD", + "BAC535EDBC4A1394BDC5975DAA781E9EC59CB3E3BD2D118193A80BB65E36E2366E97" + "48FB913F580C85C99E7BDCC13ADD" + }, + { /* tv 191 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942626", + "4099952208B4889600A5EBBCB13E1A32692BEFB0733B41E6DCC614E42E5805F81701" + "2A991AF1F486CAF3A9ADD9FFCC03", + "A1306B8887CCFA67C6B8BA6B509FCA67E9C52C07FF752F32648682D880DC774BFB25" + "B2CF55697F13059AF10B1DC4F65F" + }, + { /* tv 192 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942627", + "D5D89C3B5282369C5FBD88E2B231511A6B80DFF0E5152CF6A464FA9428A8583BAC8E" + "BC773D157811A462B892401DAFCF", + "27EADD621ED6F92DBE7E92A1656BB70E2BE2B03BF1D5C42463545A81BBF585442EDE" + "F3460B640DDC97DD48AB1454C98C" + }, + { /* tv 193 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942628", + "B3D13FC8B32B01058CC15C11D813525522A94156FFF01C205B21F9F7DA7C4E9CA849" + "557A10B6383B4B88701A9606860B", + "EAD6E618206E9D59E4FB64DAC9E9B4E411453B5EE28B650B7B2EEEBC8C2040257C72" + "DB064D7B50AF67A2A773CC08429D" + }, + { /* tv 194 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942629", + "E8C8F94D44FBC2396BBEAC481B89D2B0877B1DFFD23E7DC95DE541EB651CCA2C41AB" + "A24DBC02DE6637209ACCF0F59EA0", + "76E51BBCA903751F6CD4340921AD3756CC479E6E188D728637CE6BEC5F62F0B603B9" + "745EAAF621DD2811A362E4984777" + }, + { /* tv 195 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942630", + "A567BA97B67AEA5BAFDAF5002FFCC6AB9632BFF9F01F873F6267BCD1F0F11C139EE5" + "F441ABD99F1BAAF1CA1E3B5CBCE7", + "21E4C74C6760CCE79BB1BEB850E9B133AE7AA6AFB96CD13F79CD641FA87A82988894" + "347C8DDE75829BDC5ED9C90BD633" + }, + { /* tv 196 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942631", + "952A7A349BD49289AB3AC421DCF683D08C2ED5E41F6D0E21648AF2691A481406DA4A" + "5E22DA817CB466DA2EA77D2A7022", + "5FCDF0507B4A43FA9CFAD215190990D1F6047FC931E75F1446FD74F69E694AF1FCE5" + "59B9768BC1DD610945341DE42E91" + }, + { /* tv 197 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942632", + "099056E27DA7B998DA1EEEC2904816C57FE935ED5837C37456C9FD14892D3F8C4749" + "B66E3AFB81D626356F3B55B4DDD8", + "D1B3F3DCB1CF5469977AFAABB53A1FC6903B1127203C9C02BC006C0BE4AD5CD9AB99" + "2AEC9C5500CA82A2457FC73A1F44" + }, + { /* tv 198 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942633", + "A669C5563BD67EEC678D29D6EF4FDE864F372D90B79B9E88931D5C29291238CCED8E" + "85AB507BF91AA9CB2D13186658FB", + "567748D5183ED860DD26F7C24A0F132208FEE6AAF3E7C3CE3AFD20873C48FA56D692" + "7E69DB7D77266887B09648C5DE22" + }, + { /* tv 199 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942634", + "8F0A39A4049BCB3EF1BF29B8B025B78F2216F7291E6FD3BAC6CB1EE285FB6E21C388" + "528BFEE2B9535C55E4461079118B", + "9D3881EBC749FE29BAD3B5ACDD3C56866564C2835C3BFF39489877AB51264CFC618B" + "C100202AE497D9D25B075399B507" + }, + { /* tv 200 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942635", + "1692778EA596E0BE75114297A6FA383445BF227FBE58190A900C3C73256F11FB5A32" + "58D6F403D5ECE6E9B269D822C87D", + "232DC9A8FF2BEF957CAC7745C24702F1DDAAB52392ADE32B42E3CF3D13F113E59452" + "1E15322E8F729095405CFDD4F52D" + }, + { /* tv 201 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942636", + "283C1D7365CE4788F29F8EBF234EDFFEAD6FE997FBEA5FFA2D58CC9DFA7B1C508B05" + "526F55B9EBB2040F05B48FB6D0E1", + "6B8A366F9E1BE47745AD102473E96FB8E59E2798128668D62636D32FE242DDA8CF27" + "B120CD5870619B99B3263AED1073" + }, + { /* tv 202 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942637", + "627BE1ACD064D2B2226FE0D26F2D15D3C33EBCBB7F0F5DA51CBD41F2625738302131" + "7D7202FF30E50937F0854E35C5DF", + "F68995B34C074E3DE41922593EB0EA8A4D36ACAD9BB088B36679B09EC8EABBE8FB3B" + "A4717B1E9ACEE8CC5BF82C0F06CB" + }, + { /* tv 203 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942638", + "11DE24A2C251C777573CAC5EA025E467F208E51DBFF98FC54F6661CBE56583B03788" + "2F4A1CA297E60ABCDBC3836D84BC", + "705969388BBF06D2F0A7C816F5FF183AD7B4BB88AB2A211773679ACC496FE513CE88" + "9791F51704CCE7BBEB55193E8EC5" + }, + { /* tv 204 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942639", + "138251CD52AC9298C1C8AAD977321DEB97E709BD0B4CA0ACA55DC8AD51DCFC9D1589" + "A1597E3A5120E1EFD631C63E1835", + "35351D679659D1E9CE175D7E7E54A99E923BA26E7543F60C54F19C3086D55B22128C" + "7840C8445A96AB60E3FE4D8F1298" + }, + { /* tv 205 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942640", + "077A41D4606FFA1464793C7E5FDC7D98CB9D3910202DCD06BEA4F240D3566DA6B408" + "BBAE5026580D02D7E5C70500C831", + "366A0835F4F3BD7C82F44169FD5603667ADF4BE37AEEA55A0897B3F123EEE1523DB5" + "42931B4A2D6749A0D7A0F5D0E20E" + }, + { /* tv 206 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942641", + "08D999057BA3D2D969260045C55B97F089025959A6F434D651D207D19FB96E9E4FE0" + "E86EBE0E64F85B96A9C75295DF61", + "717F0E05A4E4C312484017200292458B4D8A278A43933BC16FB1AFA0DA954BD9A002" + "BC15B2C61DD29EAFE190F56BF17F" + }, + { /* tv 207 */ + "NIST P-384", + "39402006196394479212279040100143613805079739270465446667946905279627" + "659399113263569398956308152294913554433653942642", + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502" + "F25DBF55296C3A545E3872760AB7", + "C9E821B569D9D390A26167406D6D23D6070BE242D765EB831625CEEC4A0F473EF59F" + "4E30E2817E6285BCE2846F15F1A0" + }, + { /* tv 208 */ + "NIST P-521", + "1", + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBA" + "A14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C" + "97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650" + }, + { /* tv 209 */ + "NIST P-521", + "2", + "00433C219024277E7E682FCB288148C282747403279B1CCC06352C6E5505D769BE97" + "B3B204DA6EF55507AA104A3A35C5AF41CF2FA364D60FD967F43E3933BA6D783D", + "00F4BB8CC7F86DB26700A7F3ECEEEED3F0B5C6B5107C4DA97740AB21A29906C42DBB" + "B3E377DE9F251F6B93937FA99A3248F4EAFCBE95EDC0F4F71BE356D661F41B02" + }, + { /* tv 210 */ + "NIST P-521", + "3", + "01A73D352443DE29195DD91D6A64B5959479B52A6E5B123D9AB9E5AD7A112D7A8DD1" + "AD3F164A3A4832051DA6BD16B59FE21BAEB490862C32EA05A5919D2EDE37AD7D", + "013E9B03B97DFA62DDD9979F86C6CAB814F2F1557FA82A9D0317D2F8AB1FA355CEEC" + "2E2DD4CF8DC575B02D5ACED1DEC3C70CF105C9BC93A590425F588CA1EE86C0E5" + }, + { /* tv 211 */ + "NIST P-521", + "4", + "0035B5DF64AE2AC204C354B483487C9070CDC61C891C5FF39AFC06C5D55541D3CEAC" + "8659E24AFE3D0750E8B88E9F078AF066A1D5025B08E5A5E2FBC87412871902F3", + "0082096F84261279D2B673E0178EB0B4ABB65521AEF6E6E32E1B5AE63FE2F19907F2" + "79F283E54BA385405224F750A95B85EEBB7FAEF04699D1D9E21F47FC346E4D0D" + }, + { /* tv 212 */ + "NIST P-521", + "5", + "00652BF3C52927A432C73DBC3391C04EB0BF7A596EFDB53F0D24CF03DAB8F177ACE4" + "383C0C6D5E3014237112FEAF137E79A329D7E1E6D8931738D5AB5096EC8F3078", + "015BE6EF1BDD6601D6EC8A2B73114A8112911CD8FE8E872E0051EDD817C9A0347087" + "BB6897C9072CF374311540211CF5FF79D1F007257354F7F8173CC3E8DEB090CB" + }, + { /* tv 213 */ + "NIST P-521", + "6", + "01EE4569D6CDB59219532EFF34F94480D195623D30977FD71CF3981506ADE4AB0152" + "5FBCCA16153F7394E0727A239531BE8C2F66E95657F380AE23731BEDF79206B9", + "01DE0255AD0CC64F586AE2DD270546E3B1112AABBB73DA5A808E7240A926201A8A96" + "CAB72D0E56648C9DF96C984DE274F2203DC7B8B55CA0DADE1EACCD7858D44F17" + }, + { /* tv 214 */ + "NIST P-521", + "7", + "0056D5D1D99D5B7F6346EEB65FDA0B073A0C5F22E0E8F5483228F018D2C2F7114C5D" + "8C308D0ABFC698D8C9A6DF30DCE3BBC46F953F50FDC2619A01CEAD882816ECD4", + "003D2D1B7D9BAAA2A110D1D8317A39D68478B5C582D02824F0DD71DBD98A26CBDE55" + "6BD0F293CDEC9E2B9523A34591CE1A5F9E76712A5DDEFC7B5C6B8BC90525251B" + }, + { /* tv 215 */ + "NIST P-521", + "8", + "000822C40FB6301F7262A8348396B010E25BD4E29D8A9B003E0A8B8A3B05F826298F" + "5BFEA5B8579F49F08B598C1BC8D79E1AB56289B5A6F4040586F9EA54AA78CE68", + "016331911D5542FC482048FDAB6E78853B9A44F8EDE9E2C0715B5083DE610677A8F1" + "89E9C0AA5911B4BFF0BA0DF065C578699F3BA940094713538AD642F11F17801C" + }, + { /* tv 216 */ + "NIST P-521", + "9", + "01585389E359E1E21826A2F5BF157156D488ED34541B988746992C4AB145B8C6B665" + "7429E1396134DA35F3C556DF725A318F4F50BABD85CD28661F45627967CBE207", + "002A2E618C9A8AEDF39F0B55557A27AE938E3088A654EE1CEBB6C825BA263DDB446E" + "0D69E5756057AC840FF56ECF4ABFD87D736C2AE928880F343AA0EA86B9AD2A4E" + }, + { /* tv 217 */ + "NIST P-521", + "10", + "0190EB8F22BDA61F281DFCFE7BB6721EC4CD901D879AC09AC7C34A9246B11ADA8910" + "A2C7C178FCC263299DAA4DA9842093F37C2E411F1A8E819A87FF09A04F2F3320", + "01EB5D96B8491614BA9DBAEAB3B0CA2BA760C2EEB2144251B20BA97FD78A62EF62D2" + "BF5349D44D9864BB536F6163DC57EBEFF3689639739FAA172954BC98135EC759" + }, + { /* tv 218 */ + "NIST P-521", + "11", + "008A75841259FDEDFF546F1A39573B4315CFED5DC7ED7C17849543EF2C54F2991652" + "F3DBC5332663DA1BD19B1AEBE3191085015C024FA4C9A902ECC0E02DDA0CDB9A", + "0096FB303FCBBA2129849D0CA877054FB2293ADD566210BD0493ED2E95D4E0B9B82B" + "1BC8A90E8B42A4AB3892331914A95336DCAC80E3F4819B5D58874F92CE48C808" + }, + { /* tv 219 */ + "NIST P-521", + "12", + "01C0D9DCEC93F8221C5DE4FAE9749C7FDE1E81874157958457B6107CF7A5967713A6" + "44E90B7C3FB81B31477FEE9A60E938013774C75C530928B17BE69571BF842D8C", + "014048B5946A4927C0FE3CE1D103A682CA4763FE65AB71494DA45E404ABF6A17C097" + "D6D18843D86FCDB6CC10A6F951B9B630884BA72224F5AE6C79E7B1A3281B17F0" + }, + { /* tv 220 */ + "NIST P-521", + "13", + "007E3E98F984C396AD9CD7865D2B4924861A93F736CDE1B4C2384EEDD2BEAF5B8661" + "32C45908E03C996A3550A5E79AB88EE94BEC3B00AB38EFF81887848D32FBCDA7", + "0108EE58EB6D781FEDA91A1926DAA3ED5A08CED50A386D5421C69C7A67AE5C1E212A" + "C1BD5D5838BC763F26DFDD351CBFBBC36199EAAF9117E9F7291A01FB022A71C9" + }, + { /* tv 221 */ + "NIST P-521", + "14", + "01875BC7DC551B1B65A9E1B8CCFAAF84DED1958B401494116A2FD4FB0BABE0B31999" + "74FC06C8B897222D79DF3E4B7BC744AA6767F6B812EFBF5D2C9E682DD3432D74", + "005CA4923575DACB5BD2D66290BBABB4BDFB8470122B8E51826A0847CE9B86D7ED62" + "D07781B1B4F3584C11E89BF1D133DC0D5B690F53A87C84BE41669F852700D54A" + }, + { /* tv 222 */ + "NIST P-521", + "15", + "006B6AD89ABCB92465F041558FC546D4300FB8FBCC30B40A0852D697B532DF128E11" + "B91CCE27DBD00FFE7875BD1C8FC0331D9B8D96981E3F92BDE9AFE337BCB8DB55", + "01B468DA271571391D6A7CE64D2333EDBF63DF0496A9BAD20CBA4B62106997485ED5" + "7E9062C899470A802148E2232C96C99246FD90CC446ABDD956343480A1475465" + }, + { /* tv 223 */ + "NIST P-521", + "16", + "01D17D10D8A89C8AD05DDA97DA26AC743B0B2A87F66192FD3F3DD632F8D20B188A52" + "943FF18861CA00A0E5965DA7985630DF0DBF5C8007DCDC533A6C508F81A8402F", + "007A37343C582D77001FC714B18D3D3E69721335E4C3B800D50EC7CA30C94B6B82C1" + "C182E1398DB547AA0B3075AC9D9988529E3004D28D18633352E272F89BC73ABE" + }, + { /* tv 224 */ + "NIST P-521", + "17", + "01B00DDB707F130EDA13A0B874645923906A99EE9E269FA2B3B4D66524F269250858" + "760A69E674FE0287DF4E799B5681380FF8C3042AF0D1A41076F817A853110AE0", + "0085683F1D7DB16576DBC111D4E4AEDDD106B799534CF69910A98D68AC2B22A1323D" + "F9DA564EF6DD0BF0D2F6757F16ADF420E6905594C2B755F535B9CB7C70E64647" + }, + { /* tv 225 */ + "NIST P-521", + "18", + "01BC33425E72A12779EACB2EDCC5B63D1281F7E86DBC7BF99A7ABD0CFE367DE4666D" + "6EDBB8525BFFE5222F0702C3096DEC0884CE572F5A15C423FDF44D01DD99C61D", + "010D06E999885B63535DE3E74D33D9E63D024FB07CE0D196F2552C8E4A00AC84C044" + "234AEB201F7A9133915D1B4B45209B9DA79FE15B19F84FD135D841E2D8F9A86A" + }, + { /* tv 226 */ + "NIST P-521", + "19", + "00998DCCE486419C3487C0F948C2D5A1A07245B77E0755DF547EFFF0ACDB3790E7F1" + "FA3B3096362669679232557D7A45970DFECF431E725BBDE478FF0B2418D6A19B", + "0137D5DA0626A021ED5CC3942497535B245D67D28AEE2B7BCF4ACC50EEE365457727" + "73AD963FF2EB8CF9B0EC39991631C377F5A4D89EA9FBFE44A9091A695BFD0575" + }, + { /* tv 227 */ + "NIST P-521", + "20", + "018BDD7F1B889598A4653DEEAE39CC6F8CC2BD767C2AB0D93FB12E968FBED342B517" + "09506339CB1049CB11DD48B9BDB3CD5CAD792E43B74E16D8E2603BFB11B0344F", + "00C5AADBE63F68CA5B6B6908296959BF0AF89EE7F52B410B9444546C550952D31120" + "4DA3BDDDC6D4EAE7EDFAEC1030DA8EF837CCB22EEE9CFC94DD3287FED0990F94" + }, + { /* tv 228 */ + "NIST P-521", + "112233445566778899", + "01650048FBD63E8C30B305BF36BD7643B91448EF2206E8A0CA84A140789A99B0423A" + "0A2533EA079CA7E049843E69E5FA2C25A163819110CEC1A30ACBBB3A422A40D8", + "010C9C64A0E0DB6052DBC5646687D06DECE5E9E0703153EFE9CB816FE025E85354D3" + "C5F869D6DB3F4C0C01B5F97919A5E72CEEBE03042E5AA99112691CFFC2724828" + }, + { /* tv 229 */ + "NIST P-521", + "112233445566778899112233445566778899", + "017E1370D39C9C63925DAEEAC571E21CAAF60BD169191BAEE8352E0F54674443B297" + "86243564ABB705F6FC0FE5FC5D3F98086B67CA0BE7AC8A9DEC421D9F1BC6B37F", + "01CD559605EAD19FBD99E83600A6A81A0489E6F20306EE0789AE00CE16A6EFEA2F42" + "F7534186CF1C60DF230BD9BCF8CB95E5028AD9820B2B1C0E15597EE54C4614A6" + }, + { /* tv 230 */ + "NIST P-521", + "17698052779751630352537759308423671290937417867253767860073493326533" + "23812656658291413435033257677579095366632521448854141275926144187294" + "499863933403633025023", + "00B45CB84651C9D4F08858B867F82D816E84E94FE4CAE3DA5F65E420B08398D0C5BF" + "019253A6C26D20671BDEF0B8E6C1D348A4B0734687F73AC6A4CBB2E085C68B3F", + "01C84942BBF538903062170A4BA8B3410D385719BA2037D29CA5248BFCBC8478220F" + "EC79244DCD45D31885A1764DEE479CE20B12CEAB62F9001C7AA4282CE4BE7F56" + }, + { /* tv 231 */ + "NIST P-521", + "10474840033715746231626262792913259631724379050679813326769821870752" + "87502926828892214143101559079638247121149165524401608805506660439970" + "30661040721887239", + "01CCEF4CDA108CEBE6568820B54A3CA3A3997E4EF0EDA6C350E7ED3DBB1861EDD801" + "81C650CEBE5440FEBA880F9C8A7A86F8B82659794F6F5B88E501E5DD84E65D7E", + "01026565F8B195D03C3F6139C3A63EAA1C29F7090AB2A8F75027939EC05109035F1B" + "38E6C508E0C14CE53AB7E2DA33AA28140EDBF3964862FB157119517454E60F07" + }, + { /* tv 232 */ + "NIST P-521", + "67039038650783458881413816514301680394966640773509650542881331265493" + "07058741788671148197429777343936466127575938031786147409472627479702" + "469884214509568000", + "00C1002DC2884EEDADB3F9B468BBEBD55980799852C506D37271FFCD006919DB3A96" + "DF8FE91EF6ED4B9081B1809E8F2C2B28AF5FCBF524147C73CB0B913D6FAB0995", + "01614E8A62C8293DD2AA6EF27D30974A4FD185019FA8EF4F982DA48698CECF706581" + "F69EE9ED67A9C231EC9D0934D0F674646153273BCBB345E923B1EC1386A1A4AD" + }, + { /* tv 233 */ + "NIST P-521", + "16759256436823953054045171656435622518800269587808965316988567370241" + "79880343339878336382412050263431942974939646683480906434632963478257" + "639757341102436352", + "010ED3E085ECDE1E66874286B5D5642B9D37853A026A0A025C7B84936E2ECEEC5F34" + "2E14C80C79CCF814D5AD085C5303F2823251F2B9276F88C9D7A43E387EBD87AC", + "01BE399A7666B29E79BBF3D277531A97CE05CAC0B49BECE4781E7AEE0D6E80FEE883" + "C76E9F08453DC1ADE4E49300F3D56FEE6A1510DA1B1F12EEAA39A05AA0508119" + }, + { /* tv 234 */ + "NIST P-521", + "12785133382149415221402495202586701798620696169446772599038235721862" + "33869219015616395155896385695905923238160286474392442745178676951515" + "4396810706943", + "013070A29B059D317AF37089E40FCB135868F52290EFF3E9F3E32CDADCA18EA234D8" + "589C665A4B8E3D0714DE004A419DEA7091A3BBA97263C438FE9413AA598FD4A5", + "00238A27FD9E5E7324C8B538EF2E334B71AC2611A95F42F4F2544D8C4A65D2A32A8B" + "AFA15EFD4FC2BD8AB2B0C51F65B680879589F4D5FE8A84CEB17A2E8D3587F011" + }, + { /* tv 235 */ + "NIST P-521", + "21452487583224925587220685549573442688947752933626165525549242527332" + "27278613418256777229473754067116763723353140430716009349416151854185" + "40320233184489636351", + "01A3D88799878EC74E66FF1AD8C7DFA9A9B4445A17F0810FF8189DD27AE3B6C580D3" + "52476DBDAEB08D7DA0DE3866F7C7FDBEBB8418E19710F1F7AFA88C22280B1404", + "00B39703D2053EC7B8812BDFEBFD81B4CB76F245FE535A1F1E46801C35DE03C15063" + "A99A203981529C146132863CA0E68544D0F0A638D8A2859D82B4DD266F27C3AE" + }, + { /* tv 236 */ + "NIST P-521", + "51140486275567859131139077890835526884648461857823088348651153840508" + "28762136685450683124474653127224662029512310426956586705594937826639" + "5604768784399", + "01D16B4365DEFE6FD356DC1F31727AF2A32C7E86C5AE87ED2950A08BC8653F203C7F" + "7860E80F95AA27C93EA76E8CD094127B15ED42CC5F96DC0A0F9A1C1E31D0D526", + "006E3710A0F9366E0BB8A14FFE8EBC2722EECF4A123EC9BA98DCCCA335D6FAFD289D" + "C69FD90903C9AC982FEB46DF93F03A7C8C9549D32C1C386D17F37340E63822A8" + }, + { /* tv 237 */ + "NIST P-521", + "66515297160252068810352799528815206278411522472127845209144250393126" + "06120198879080839643311347169019249080198239408356563413447402270445" + "462102068592377843", + "01B1220F67C985E9FC9C588C0C86BB16E6FE4CC11E168A98D701AE4670724B3D030E" + "D9965FADF4207C7A1BE9BE0F40DEF2BBFFF0C7EABCB5B42526CE1D3CAA468F52", + "006CDAD2860F6D2C37159A5A866D11605F2E7D87430DCFE6E6816AB6423CD9003CA6" + "F2527B9C2A2483C541D456C963D18A0D2A46E158CB2A44C0BF42D562881FB748" + }, + { /* tv 238 */ + "NIST P-521", + "32245518246132322325376800779468186601568352887780873448053703978113" + "79731631671254853846826682273677870214778462237171365140390183770226" + "853329363961324241919", + "00F25E545213C8C074BE38A0612EA9B66336B14A874372548D9716392DFA31CD0D13" + "E94F86CD48B8D43B80B5299144E01245C873B39F6AC6C4FB397746AF034AD67C", + "01733ABB21147CC27E35F41FAF40290AFD1EEB221D983FFABBD88E5DC8776450A409" + "EACDC1BCA2B9F517289C68645BB96781808FEAE42573C2BB289F16E2AECECE17" + }, + { /* tv 239 */ + "NIST P-521", + "12486613128442885430380874043991285080254917488396284953815149251315" + "41260063458153906666309229761204066997801762358775284540965316727702" + "1864132608", + "0172CD22CBE0634B6BFEE24BB1D350F384A945ED618ECAD48AADC6C1BC0DCC107F0F" + "FE9FE14DC929F90153F390C25BE5D3A73A56F9ACCB0C72C768753869732D0DC4", + "00D249CFB570DA4CC48FB5426A928B43D7922F787373B6182408FBC71706E7527E84" + "14C79167F3C999FF58DE352D238F1FE7168C658D338F72696F2F889A97DE23C5" + }, + { /* tv 240 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005429", + "018BDD7F1B889598A4653DEEAE39CC6F8CC2BD767C2AB0D93FB12E968FBED342B517" + "09506339CB1049CB11DD48B9BDB3CD5CAD792E43B74E16D8E2603BFB11B0344F", + "013A552419C09735A49496F7D696A640F50761180AD4BEF46BBBAB93AAF6AD2CEEDF" + "B25C4222392B1518120513EFCF257107C8334DD11163036B22CD78012F66F06B" + }, + { /* tv 241 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005430", + "00998DCCE486419C3487C0F948C2D5A1A07245B77E0755DF547EFFF0ACDB3790E7F1" + "FA3B3096362669679232557D7A45970DFECF431E725BBDE478FF0B2418D6A19B", + "00C82A25F9D95FDE12A33C6BDB68ACA4DBA2982D7511D48430B533AF111C9ABA88D8" + "8C5269C00D1473064F13C666E9CE3C880A5B2761560401BB56F6E596A402FA8A" + }, + { /* tv 242 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005431", + "01BC33425E72A12779EACB2EDCC5B63D1281F7E86DBC7BF99A7ABD0CFE367DE4666D" + "6EDBB8525BFFE5222F0702C3096DEC0884CE572F5A15C423FDF44D01DD99C61D", + "00F2F9166677A49CACA21C18B2CC2619C2FDB04F831F2E690DAAD371B5FF537B3FBB" + "DCB514DFE0856ECC6EA2E4B4BADF646258601EA4E607B02ECA27BE1D27065795" + }, + { /* tv 243 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005432", + "01B00DDB707F130EDA13A0B874645923906A99EE9E269FA2B3B4D66524F269250858" + "760A69E674FE0287DF4E799B5681380FF8C3042AF0D1A41076F817A853110AE0", + "017A97C0E2824E9A89243EEE2B1B51222EF94866ACB30966EF56729753D4DD5ECDC2" + "0625A9B10922F40F2D098A80E9520BDF196FAA6B3D48AA0ACA4634838F19B9B8" + }, + { /* tv 244 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005433", + "01D17D10D8A89C8AD05DDA97DA26AC743B0B2A87F66192FD3F3DD632F8D20B188A52" + "943FF18861CA00A0E5965DA7985630DF0DBF5C8007DCDC533A6C508F81A8402F", + "0185C8CBC3A7D288FFE038EB4E72C2C1968DECCA1B3C47FF2AF13835CF36B4947D3E" + "3E7D1EC6724AB855F4CF8A53626677AD61CFFB2D72E79CCCAD1D8D076438C541" + }, + { /* tv 245 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005434", + "006B6AD89ABCB92465F041558FC546D4300FB8FBCC30B40A0852D697B532DF128E11" + "B91CCE27DBD00FFE7875BD1C8FC0331D9B8D96981E3F92BDE9AFE337BCB8DB55", + "004B9725D8EA8EC6E2958319B2DCCC12409C20FB6956452DF345B49DEF9668B7A12A" + "816F9D3766B8F57FDEB71DDCD369366DB9026F33BB954226A9CBCB7F5EB8AB9A" + }, + { /* tv 246 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005435", + "01875BC7DC551B1B65A9E1B8CCFAAF84DED1958B401494116A2FD4FB0BABE0B31999" + "74FC06C8B897222D79DF3E4B7BC744AA6767F6B812EFBF5D2C9E682DD3432D74", + "01A35B6DCA8A2534A42D299D6F44544B42047B8FEDD471AE7D95F7B831647928129D" + "2F887E4E4B0CA7B3EE17640E2ECC23F2A496F0AC57837B41BE99607AD8FF2AB5" + }, + { /* tv 247 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005436", + "007E3E98F984C396AD9CD7865D2B4924861A93F736CDE1B4C2384EEDD2BEAF5B8661" + "32C45908E03C996A3550A5E79AB88EE94BEC3B00AB38EFF81887848D32FBCDA7", + "00F711A7149287E01256E5E6D9255C12A5F7312AF5C792ABDE3963859851A3E1DED5" + "3E42A2A7C74389C0D92022CAE340443C9E6615506EE81608D6E5FE04FDD58E36" + }, + { /* tv 248 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005437", + "01C0D9DCEC93F8221C5DE4FAE9749C7FDE1E81874157958457B6107CF7A5967713A6" + "44E90B7C3FB81B31477FEE9A60E938013774C75C530928B17BE69571BF842D8C", + "00BFB74A6B95B6D83F01C31E2EFC597D35B89C019A548EB6B25BA1BFB54095E83F68" + "292E77BC2790324933EF5906AE4649CF77B458DDDB0A519386184E5CD7E4E80F" + }, + { /* tv 249 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005438", + "008A75841259FDEDFF546F1A39573B4315CFED5DC7ED7C17849543EF2C54F2991652" + "F3DBC5332663DA1BD19B1AEBE3191085015C024FA4C9A902ECC0E02DDA0CDB9A", + "016904CFC03445DED67B62F35788FAB04DD6C522A99DEF42FB6C12D16A2B1F4647D4" + "E43756F174BD5B54C76DCCE6EB56ACC923537F1C0B7E64A2A778B06D31B737F7" + }, + { /* tv 250 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005439", + "0190EB8F22BDA61F281DFCFE7BB6721EC4CD901D879AC09AC7C34A9246B11ADA8910" + "A2C7C178FCC263299DAA4DA9842093F37C2E411F1A8E819A87FF09A04F2F3320", + "0014A26947B6E9EB456245154C4F35D4589F3D114DEBBDAE4DF4568028759D109D2D" + "40ACB62BB2679B44AC909E9C23A814100C9769C68C6055E8D6AB4367ECA138A6" + }, + { /* tv 251 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005440", + "01585389E359E1E21826A2F5BF157156D488ED34541B988746992C4AB145B8C6B665" + "7429E1396134DA35F3C556DF725A318F4F50BABD85CD28661F45627967CBE207", + "01D5D19E736575120C60F4AAAA85D8516C71CF7759AB11E3144937DA45D9C224BB91" + "F2961A8A9FA8537BF00A9130B54027828C93D516D777F0CBC55F15794652D5B1" + }, + { /* tv 252 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005441", + "000822C40FB6301F7262A8348396B010E25BD4E29D8A9B003E0A8B8A3B05F826298F" + "5BFEA5B8579F49F08B598C1BC8D79E1AB56289B5A6F4040586F9EA54AA78CE68", + "009CCE6EE2AABD03B7DFB7025491877AC465BB0712161D3F8EA4AF7C219EF988570E" + "76163F55A6EE4B400F45F20F9A3A879660C456BFF6B8ECAC7529BD0EE0E87FE3" + }, + { /* tv 253 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005442", + "0056D5D1D99D5B7F6346EEB65FDA0B073A0C5F22E0E8F5483228F018D2C2F7114C5D" + "8C308D0ABFC698D8C9A6DF30DCE3BBC46F953F50FDC2619A01CEAD882816ECD4", + "01C2D2E48264555D5EEF2E27CE85C6297B874A3A7D2FD7DB0F228E242675D93421AA" + "942F0D6C321361D46ADC5CBA6E31E5A061898ED5A2210384A3947436FADADAE4" + }, + { /* tv 254 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005443", + "01EE4569D6CDB59219532EFF34F94480D195623D30977FD71CF3981506ADE4AB0152" + "5FBCCA16153F7394E0727A239531BE8C2F66E95657F380AE23731BEDF79206B9", + "0021FDAA52F339B0A7951D22D8FAB91C4EEED554448C25A57F718DBF56D9DFE57569" + "3548D2F1A99B7362069367B21D8B0DDFC238474AA35F2521E1533287A72BB0E8" + }, + { /* tv 255 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005444", + "00652BF3C52927A432C73DBC3391C04EB0BF7A596EFDB53F0D24CF03DAB8F177ACE4" + "383C0C6D5E3014237112FEAF137E79A329D7E1E6D8931738D5AB5096EC8F3078", + "00A41910E42299FE291375D48CEEB57EED6EE327017178D1FFAE1227E8365FCB8F78" + "44976836F8D30C8BCEEABFDEE30A00862E0FF8DA8CAB0807E8C33C17214F6F34" + }, + { /* tv 256 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005445", + "0035B5DF64AE2AC204C354B483487C9070CDC61C891C5FF39AFC06C5D55541D3CEAC" + "8659E24AFE3D0750E8B88E9F078AF066A1D5025B08E5A5E2FBC87412871902F3", + "017DF6907BD9ED862D498C1FE8714F4B5449AADE5109191CD1E4A519C01D0E66F80D" + "860D7C1AB45C7ABFADDB08AF56A47A114480510FB9662E261DE0B803CB91B2F2" + }, + { /* tv 257 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005446", + "01A73D352443DE29195DD91D6A64B5959479B52A6E5B123D9AB9E5AD7A112D7A8DD1" + "AD3F164A3A4832051DA6BD16B59FE21BAEB490862C32EA05A5919D2EDE37AD7D", + "00C164FC4682059D2226686079393547EB0D0EAA8057D562FCE82D0754E05CAA3113" + "D1D22B30723A8A4FD2A5312E213C38F30EFA36436C5A6FBDA0A7735E11793F1A" + }, + { /* tv 258 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005447", + "00433C219024277E7E682FCB288148C282747403279B1CCC06352C6E5505D769BE97" + "B3B204DA6EF55507AA104A3A35C5AF41CF2FA364D60FD967F43E3933BA6D783D", + "010B44733807924D98FF580C1311112C0F4A394AEF83B25688BF54DE5D66F93BD244" + "4C1C882160DAE0946C6C805665CDB70B1503416A123F0B08E41CA9299E0BE4FD" + }, + { /* tv 259 */ + "NIST P-521", + "68647976601306097149819007990813932172694353001433054093944634591855" + "43183397655394245057746333217197532963996371363321113864768612440380" + "340372808892707005448", + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBA" + "A14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", + "00E7C6D6958765C43FFBA375A04BD382E426670ABBB6A864BB97E85042E8D8C199D3" + "68118D66A10BD9BF3AAF46FEC052F89ECAC38F795D8D3DBF77416B89602E99AF" + }, + + { NULL, NULL, NULL, NULL } + }; + gpg_error_t err; + gcry_ctx_t ctx; + gcry_mpi_t k, x, y; + gcry_mpi_point_t G, Q; + int idx; + + for (idx = 0; tv[idx].curve; idx++) + { + /* P-192 is not supported in fips mode */ + if (gcry_fips_mode_active()) + { + if (!strcmp(tv[idx].curve, "NIST P-192")) + { + static int once; + if (!once) + info ("skipping %s in fips mode\n", tv[idx].curve); + once = 1; + continue; + } + } + + err = gcry_mpi_ec_new (&ctx, NULL, tv[idx].curve); + if (err) + { + fail ("tv[%d].'%s': can't create context: %s\n", + idx, tv[idx].curve, gpg_strerror (err)); + return; + } + + G = gcry_mpi_ec_get_point ("g", ctx, 1); + if (!G) + { + fail ("tv[%d].'%s': error getting point parameter 'g'\n", + idx, tv[idx].curve); + return; + } + + if (tv[idx].k_base10) + k = mpi_base10_scan (tv[idx].k_base10); + else + die ("tv[%d].'%s': missing 'k'\n", + idx, tv[idx].curve); + + Q = gcry_mpi_point_new (0); + x = gcry_mpi_new (0); + y = gcry_mpi_new (0); + + gcry_mpi_ec_mul (Q, k, G, ctx); + if (gcry_mpi_ec_get_affine (x, y, Q, ctx)) + { + fail ("tv[%d].'%s': failed to get affine coordinates\n", + idx, tv[idx].curve); + return; + } + + if (cmp_mpihex (x, tv[idx].qx) || cmp_mpihex (y, tv[idx].qy)) + { + fail ("tv[%d].'%s': sample point multiply failed:\n", + idx, tv[idx].curve); + print_mpi (" k", k); + print_mpi (" Qx", x); + printf ("expected Qx: %s\n", tv[idx].qx); + print_mpi (" Qy", y); + printf ("expected Qy: %s\n", tv[idx].qy); + } + + gcry_mpi_release (k); + gcry_mpi_release (y); + gcry_mpi_release (x); + gcry_mpi_point_release (Q); + gcry_mpi_point_release (G); + gcry_ctx_release (ctx); + } +} + + int main (int argc, char **argv) { @@ -1310,6 +3305,7 @@ main (int argc, char **argv) context_param (); basic_ec_math (); point_on_curve (); + check_ec_mul (); /* The tests are for P-192 and ed25519 which are not supported in FIPS mode. */ -- 2.30.2 From jussi.kivilinna at iki.fi Mon Apr 26 23:00:45 2021 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 27 Apr 2021 00:00:45 +0300 Subject: [PATCH 7/8] mpi/ec: add fast reduction functions for NIST curves In-Reply-To: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> References: <20210426210046.4157764-1-jussi.kivilinna@iki.fi> Message-ID: <20210426210046.4157764-7-jussi.kivilinna@iki.fi> * configure.ac (ASM_DISABLED): New. * mpi/Makefile.am: Add 'ec-nist.c' and 'ec-inline.h'. * mpi/ec-nist.c: New. * mpi/ec-inline.h: New. * mpi/ec-internal.h (_gcry_mpi_ec_nist192_mod) (_gcry_mpi_ec_nist224_mod, _gcry_mpi_ec_nist256_mod) (_gcry_mpi_ec_nist384_mod, _gcry_mpi_ec_nist521_mod): New. * mpi/ec.c (ec_addm, ec_subm, ec_mulm, ec_mul2): Use 'ctx->mod'. (field_table): Add 'mod' function; Add NIST reduction functions. (ec_p_init): Setup ctx->mod; Setup function pointers from field_table only if pointer is not NULL; Resize ctx->a and ctx->b only if set. * mpi/mpi-internal.h (RESIZE_AND_CLEAR_IF_NEEDED): New. * mpi/mpiutil.c (_gcry_mpi_resize): Clear all unused limbs also in realloc case. * src/ec-context.h (mpi_ec_ctx_s): Add 'mod' function. -- Benchmark on AMD Ryzen 7 5800X (x86_64): Before: NIST-P192 | nanosecs/iter cycles/iter auto Mhz mult | 283346 1369473 4833 keygen | 1688442 8185744 4848 sign | 549683 2662984 4845 verify | 615284 2984325 4850 = NIST-P224 | nanosecs/iter cycles/iter auto Mhz mult | 516443 2501173 4843 keygen | 2859746 13866802 4849 sign | 918472 4455043 4850 verify | 1057940 5131372 4850 = NIST-P256 | nanosecs/iter cycles/iter auto Mhz mult | 423536 2054040 4850 keygen | 2383097 11557572 4850 sign | 774346 3754243 4848 verify | 864934 4196315 4852 = NIST-P384 | nanosecs/iter cycles/iter auto Mhz mult | 929985 4511881 4852 keygen | 5230788 25367299 4850 sign | 1671432 8109726 4852 verify | 1902729 9228568 4850 = NIST-P521 | nanosecs/iter cycles/iter auto Mhz mult | 2123546 10300952 4851 keygen | 12019340 58297774 4850 sign | 3886988 18853054 4850 verify | 4507885 21864015 4850 After (P192 ~40% faster, P224 ~75%, P256 ~20%, P384 ~30%, P521 ~70%): NIST-P192 | nanosecs/iter cycles/iter auto Mhz mult | 202359 981824 4852 keygen | 1200904 5826518 4852 sign | 401894 1949316 4850 verify | 423803 2056328 4852 = NIST-P224 | nanosecs/iter cycles/iter auto Mhz mult | 263122 1276615 4852 keygen | 1597091 7744280 4849 sign | 533359 2586848 4850 verify | 566961 2749355 4849 = NIST-P256 | nanosecs/iter cycles/iter auto Mhz mult | 327378 1587801 4850 keygen | 1940152 9412679 4852 sign | 635126 3080381 4850 verify | 696237 3377836 4852 = NIST-P384 | nanosecs/iter cycles/iter auto Mhz mult | 679447 3295097 4850 keygen | 3947485 19153305 4852 sign | 1299829 6304910 4851 verify | 1432189 6947326 4851 = NIST-P521 | nanosecs/iter cycles/iter auto Mhz mult | 1193042 5783179 4847 keygen | 7066699 34268023 4849 sign | 2316380 11243342 4854 verify | 2561696 12427975 4851 Benchmark on AMD Ryzen 7 5800X (i386): Before: NIST-P192 | nanosecs/iter cycles/iter auto Mhz mult | 648039 3143236 4850 keygen | 3554452 17244822 4852 sign | 1163173 5641932 4850 verify | 1300076 6305673 4850 = NIST-P224 | nanosecs/iter cycles/iter auto Mhz mult | 798607 3874405 4851 keygen | 4657604 22589864 4850 sign | 1515803 7352049 4850 verify | 1635470 7935373 4852 = NIST-P256 | nanosecs/iter cycles/iter auto Mhz mult | 927033 4496283 4850 keygen | 5313601 25771983 4850 sign | 1735795 8418514 4850 verify | 1945804 9438212 4851 = NIST-P384 | nanosecs/iter cycles/iter auto Mhz mult | 2301781 11164473 4850 keygen | 12856001 62353242 4850 sign | 4161041 20180651 4850 verify | 4705961 22827478 4851 = NIST-P521 | nanosecs/iter cycles/iter auto Mhz mult | 6066635 29422721 4850 keygen | 32995868 160046407 4850 sign | 10503306 50945387 4850 verify | 12225252 59294323 4850 After (P192 ~30% faster, P224 ~30%, P256 ~15%, P384 ~30%, P512 ~60%): NIST-P192 | nanosecs/iter cycles/iter auto Mhz mult | 447264 2171704 4856 keygen | 2663624 12919311 4850 sign | 888711 4310193 4850 verify | 953472 4625715 4851 = NIST-P224 | nanosecs/iter cycles/iter auto Mhz mult | 583938 2832214 4850 keygen | 3586202 17400678 4852 sign | 1161292 5632489 4850 verify | 1290940 6260807 4850 = NIST-P256 | nanosecs/iter cycles/iter auto Mhz mult | 776855 3767916 4850 keygen | 4602972 22319865 4849 sign | 1515662 7351140 4850 verify | 1670549 8102798 4850 = NIST-P384 | nanosecs/iter cycles/iter auto Mhz mult | 1723216 8357338 4850 keygen | 9917621 48103110 4850 sign | 3245974 15742417 4850 verify | 3611383 17517179 4851 = NIST-P521 | nanosecs/iter cycles/iter auto Mhz mult | 3407184 16523457 4850 keygen | 20007819 97041269 4850 sign | 6556658 31799190 4850 verify | 7185487 34853568 4851 Signed-off-by: Jussi Kivilinna --- configure.ac | 3 + mpi/Makefile.am | 2 +- mpi/ec-inline.h | 1141 ++++++++++++++++++++++++++++++++++++++++++++ mpi/ec-internal.h | 16 + mpi/ec-nist.c | 787 ++++++++++++++++++++++++++++++ mpi/ec.c | 90 +++- mpi/mpi-internal.h | 5 + mpi/mpiutil.c | 2 +- src/ec-context.h | 1 + 9 files changed, 2029 insertions(+), 18 deletions(-) create mode 100644 mpi/ec-inline.h create mode 100644 mpi/ec-nist.c diff --git a/configure.ac b/configure.ac index a874c411..9017efc7 100644 --- a/configure.ac +++ b/configure.ac @@ -546,6 +546,9 @@ AC_ARG_ENABLE([asm], [try_asm_modules=$enableval], [try_asm_modules=yes]) AC_MSG_RESULT($try_asm_modules) +if test "$try_asm_modules" != yes ; then + AC_DEFINE(ASM_DISABLED,1,[Defined if --disable-asm was used to configure]) +fi # Implementation of the --enable-m-guard switch. AC_MSG_CHECKING([whether memory guard is requested]) diff --git a/mpi/Makefile.am b/mpi/Makefile.am index d06594e1..adb8e6f5 100644 --- a/mpi/Makefile.am +++ b/mpi/Makefile.am @@ -175,5 +175,5 @@ libmpi_la_SOURCES = longlong.h \ mpih-mul.c \ mpih-const-time.c \ mpiutil.c \ - ec.c ec-internal.h ec-ed25519.c + ec.c ec-internal.h ec-ed25519.c ec-nist.c ec-inline.h EXTRA_libmpi_la_SOURCES = asm-common-aarch64.h diff --git a/mpi/ec-inline.h b/mpi/ec-inline.h new file mode 100644 index 00000000..e77e6c15 --- /dev/null +++ b/mpi/ec-inline.h @@ -0,0 +1,1141 @@ +/* ec-inline.h - EC inline addition/substraction helpers + * Copyright (C) 2021 Jussi Kivilinna + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#ifndef GCRY_EC_INLINE_H +#define GCRY_EC_INLINE_H + + +#if BYTES_PER_MPI_LIMB == 8 + +/* 64-bit limb definitions for 64-bit architectures. */ + +#define LIMBS_PER_LIMB64 1 +#define LOAD64(x, pos) ((x)[pos]) +#define STORE64(x, pos, v) ((x)[pos] = (mpi_limb_t)(v)) +#define LIMB_TO64(v) ((mpi_limb_t)(v)) +#define LIMB_FROM64(v) ((mpi_limb_t)(v)) +#define HIBIT_LIMB64(v) ((mpi_limb_t)(v) >> (BITS_PER_MPI_LIMB - 1)) +#define HI32_LIMB64(v) (u32)((mpi_limb_t)(v) >> (BITS_PER_MPI_LIMB - 32)) +#define LO32_LIMB64(v) ((u32)(v)) +#define LIMB64_C(hi, lo) (((mpi_limb_t)(u32)(hi) << 32) | (u32)(lo)) +#define STORE64_COND(x, pos, mask1, val1, mask2, val2) \ + ((x)[(pos)] = ((mask1) & (val1)) | ((mask2) & (val2))) + +typedef mpi_limb_t mpi_limb64_t; + +static inline u32 +LOAD32(mpi_ptr_t x, unsigned int pos) +{ + unsigned int shr = (pos % 2) * 32; + return (x[pos / 2] >> shr); +} + +static inline mpi_limb64_t +LIMB64_HILO(u32 hi, u32 lo) +{ + mpi_limb64_t v = hi; + return (v << 32) | lo; +} + + +/* x86-64 addition/subtraction helpers. */ +#if defined (__x86_64__) && defined(HAVE_CPU_ARCH_X86) && __GNUC__ >= 4 + +#define ADD3_LIMB64(A2, A1, A0, B2, B1, B0, C2, C1, C0) \ + __asm__ ("addq %8, %2\n" \ + "adcq %7, %1\n" \ + "adcq %6, %0\n" \ + : "=r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B2)), \ + "1" ((mpi_limb_t)(B1)), \ + "2" ((mpi_limb_t)(B0)), \ + "g" ((mpi_limb_t)(C2)), \ + "g" ((mpi_limb_t)(C1)), \ + "g" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB3_LIMB64(A3, A2, A1, A0, B2, B1, B0, C2, C1, C0) \ + __asm__ ("subq %8, %2\n" \ + "sbbq %7, %1\n" \ + "sbbq %6, %0\n" \ + : "=r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B2)), \ + "1" ((mpi_limb_t)(B1)), \ + "2" ((mpi_limb_t)(B0)), \ + "g" ((mpi_limb_t)(C2)), \ + "g" ((mpi_limb_t)(C1)), \ + "g" ((mpi_limb_t)(C0)) \ + : "cc") + +#define ADD4_LIMB64(A3, A2, A1, A0, B3, B2, B1, B0, C3, C2, C1, C0) \ + __asm__ ("addq %11, %3\n" \ + "adcq %10, %2\n" \ + "adcq %9, %1\n" \ + "adcq %8, %0\n" \ + : "=r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B3)), \ + "1" ((mpi_limb_t)(B2)), \ + "2" ((mpi_limb_t)(B1)), \ + "3" ((mpi_limb_t)(B0)), \ + "g" ((mpi_limb_t)(C3)), \ + "g" ((mpi_limb_t)(C2)), \ + "g" ((mpi_limb_t)(C1)), \ + "g" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB4_LIMB64(A3, A2, A1, A0, B3, B2, B1, B0, C3, C2, C1, C0) \ + __asm__ ("subq %11, %3\n" \ + "sbbq %10, %2\n" \ + "sbbq %9, %1\n" \ + "sbbq %8, %0\n" \ + : "=r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B3)), \ + "1" ((mpi_limb_t)(B2)), \ + "2" ((mpi_limb_t)(B1)), \ + "3" ((mpi_limb_t)(B0)), \ + "g" ((mpi_limb_t)(C3)), \ + "g" ((mpi_limb_t)(C2)), \ + "g" ((mpi_limb_t)(C1)), \ + "g" ((mpi_limb_t)(C0)) \ + : "cc") + +#define ADD5_LIMB64(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0, \ + C4, C3, C2, C1, C0) \ + __asm__ ("addq %14, %4\n" \ + "adcq %13, %3\n" \ + "adcq %12, %2\n" \ + "adcq %11, %1\n" \ + "adcq %10, %0\n" \ + : "=r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B4)), \ + "1" ((mpi_limb_t)(B3)), \ + "2" ((mpi_limb_t)(B2)), \ + "3" ((mpi_limb_t)(B1)), \ + "4" ((mpi_limb_t)(B0)), \ + "g" ((mpi_limb_t)(C4)), \ + "g" ((mpi_limb_t)(C3)), \ + "g" ((mpi_limb_t)(C2)), \ + "g" ((mpi_limb_t)(C1)), \ + "g" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB5_LIMB64(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0, \ + C4, C3, C2, C1, C0) \ + __asm__ ("subq %14, %4\n" \ + "sbbq %13, %3\n" \ + "sbbq %12, %2\n" \ + "sbbq %11, %1\n" \ + "sbbq %10, %0\n" \ + : "=r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B4)), \ + "1" ((mpi_limb_t)(B3)), \ + "2" ((mpi_limb_t)(B2)), \ + "3" ((mpi_limb_t)(B1)), \ + "4" ((mpi_limb_t)(B0)), \ + "g" ((mpi_limb_t)(C4)), \ + "g" ((mpi_limb_t)(C3)), \ + "g" ((mpi_limb_t)(C2)), \ + "g" ((mpi_limb_t)(C1)), \ + "g" ((mpi_limb_t)(C0)) \ + : "cc") + +#define ADD7_LIMB64(A6, A5, A4, A3, A2, A1, A0, B6, B5, B4, B3, B2, B1, B0, \ + C6, C5, C4, C3, C2, C1, C0) do { \ + mpi_limb64_t __C[7] = { C0, C1, C2, C3, C4, C5, C6 }; \ + __asm__ ("addq 0*8(%14), %6\n" \ + "adcq 1*8(%14), %5\n" \ + "adcq 2*8(%14), %4\n" \ + "adcq 3*8(%14), %3\n" \ + "adcq 4*8(%14), %2\n" \ + "adcq 5*8(%14), %1\n" \ + "adcq 6*8(%14), %0\n" \ + : "=r" (A6), \ + "=&r" (A5), \ + "=&r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B6)), \ + "1" ((mpi_limb_t)(B5)), \ + "2" ((mpi_limb_t)(B4)), \ + "3" ((mpi_limb_t)(B3)), \ + "4" ((mpi_limb_t)(B2)), \ + "5" ((mpi_limb_t)(B1)), \ + "6" ((mpi_limb_t)(B0)), \ + "r" (__C) \ + : "cc", "memory"); \ + } while (0) + +#define SUB7_LIMB64(A6, A5, A4, A3, A2, A1, A0, B6, B5, B4, B3, B2, B1, B0, \ + C6, C5, C4, C3, C2, C1, C0) do { \ + mpi_limb64_t __C[7] = { C0, C1, C2, C3, C4, C5, C6 }; \ + __asm__ ("subq 0*8(%14), %6\n" \ + "sbbq 1*8(%14), %5\n" \ + "sbbq 2*8(%14), %4\n" \ + "sbbq 3*8(%14), %3\n" \ + "sbbq 4*8(%14), %2\n" \ + "sbbq 5*8(%14), %1\n" \ + "sbbq 6*8(%14), %0\n" \ + : "=r" (A6), \ + "=&r" (A5), \ + "=&r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B6)), \ + "1" ((mpi_limb_t)(B5)), \ + "2" ((mpi_limb_t)(B4)), \ + "3" ((mpi_limb_t)(B3)), \ + "4" ((mpi_limb_t)(B2)), \ + "5" ((mpi_limb_t)(B1)), \ + "6" ((mpi_limb_t)(B0)), \ + "r" (__C) \ + : "cc", "memory"); \ + } while (0) + +#endif /* __x86_64__ */ + + +/* ARM AArch64 addition/subtraction helpers. */ +#if defined (__aarch64__) && defined(HAVE_CPU_ARCH_ARM) && __GNUC__ >= 4 + +#define ADD3_LIMB64(A2, A1, A0, B2, B1, B0, C2, C1, C0) \ + __asm__ ("adds %2, %5, %8\n" \ + "adcs %1, %4, %7\n" \ + "adc %0, %3, %6\n" \ + : "=r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB3_LIMB64(A2, A1, A0, B2, B1, B0, C2, C1, C0) \ + __asm__ ("subs %2, %5, %8\n" \ + "sbcs %1, %4, %7\n" \ + "sbc %0, %3, %6\n" \ + : "=r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define ADD4_LIMB64(A3, A2, A1, A0, B3, B2, B1, B0, C3, C2, C1, C0) \ + __asm__ ("adds %3, %7, %11\n" \ + "adcs %2, %6, %10\n" \ + "adcs %1, %5, %9\n" \ + "adc %0, %4, %8\n" \ + : "=r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB4_LIMB64(A3, A2, A1, A0, B3, B2, B1, B0, C3, C2, C1, C0) \ + __asm__ ("subs %3, %7, %11\n" \ + "sbcs %2, %6, %10\n" \ + "sbcs %1, %5, %9\n" \ + "sbc %0, %4, %8\n" \ + : "=r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define ADD5_LIMB64(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0, \ + C4, C3, C2, C1, C0) \ + __asm__ ("adds %4, %9, %14\n" \ + "adcs %3, %8, %13\n" \ + "adcs %2, %7, %12\n" \ + "adcs %1, %6, %11\n" \ + "adc %0, %5, %10\n" \ + : "=r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B4)), \ + "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C4)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB5_LIMB64(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0, \ + C4, C3, C2, C1, C0) \ + __asm__ ("subs %4, %9, %14\n" \ + "sbcs %3, %8, %13\n" \ + "sbcs %2, %7, %12\n" \ + "sbcs %1, %6, %11\n" \ + "sbc %0, %5, %10\n" \ + : "=r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B4)), \ + "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C4)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define ADD7_LIMB64(A6, A5, A4, A3, A2, A1, A0, B6, B5, B4, B3, B2, B1, B0, \ + C6, C5, C4, C3, C2, C1, C0) \ + __asm__ ("adds %6, %13, %20\n" \ + "adcs %5, %12, %19\n" \ + "adcs %4, %11, %18\n" \ + "adcs %3, %10, %17\n" \ + "adcs %2, %9, %16\n" \ + "adcs %1, %8, %15\n" \ + "adc %0, %7, %14\n" \ + : "=r" (A6), \ + "=&r" (A5), \ + "=&r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B6)), \ + "r" ((mpi_limb_t)(B5)), \ + "r" ((mpi_limb_t)(B4)), \ + "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C6)), \ + "r" ((mpi_limb_t)(C5)), \ + "r" ((mpi_limb_t)(C4)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB7_LIMB64(A6, A5, A4, A3, A2, A1, A0, B6, B5, B4, B3, B2, B1, B0, \ + C6, C5, C4, C3, C2, C1, C0) \ + __asm__ ("subs %6, %13, %20\n" \ + "sbcs %5, %12, %19\n" \ + "sbcs %4, %11, %18\n" \ + "sbcs %3, %10, %17\n" \ + "sbcs %2, %9, %16\n" \ + "sbcs %1, %8, %15\n" \ + "sbc %0, %7, %14\n" \ + : "=r" (A6), \ + "=&r" (A5), \ + "=&r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B6)), \ + "r" ((mpi_limb_t)(B5)), \ + "r" ((mpi_limb_t)(B4)), \ + "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C6)), \ + "r" ((mpi_limb_t)(C5)), \ + "r" ((mpi_limb_t)(C4)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#endif /* __aarch64__ */ + + +/* PowerPC64 addition/subtraction helpers. */ +#if defined (__powerpc__) && defined(HAVE_CPU_ARCH_PPC) && __GNUC__ >= 4 + +#define ADD3_LIMB64(A2, A1, A0, B2, B1, B0, C2, C1, C0) \ + __asm__ ("addc %2, %8, %5\n" \ + "adde %1, %7, %4\n" \ + "adde %0, %6, %3\n" \ + : "=r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc", "r0") + +#define SUB3_LIMB64(A2, A1, A0, B2, B1, B0, C2, C1, C0) \ + __asm__ ("subfc %2, %8, %5\n" \ + "subfe %1, %7, %4\n" \ + "subfe %0, %6, %3\n" \ + : "=r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc", "r0") + +#define ADD4_LIMB64(A3, A2, A1, A0, B3, B2, B1, B0, C3, C2, C1, C0) \ + __asm__ ("addc %3, %11, %7\n" \ + "adde %2, %10, %6\n" \ + "adde %1, %9, %5\n" \ + "adde %0, %8, %4\n" \ + : "=r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB4_LIMB64(A3, A2, A1, A0, B3, B2, B1, B0, C3, C2, C1, C0) \ + __asm__ ("subfc %3, %11, %7\n" \ + "subfe %2, %10, %6\n" \ + "subfe %1, %9, %5\n" \ + "subfe %0, %8, %4\n" \ + : "=r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define ADD5_LIMB64(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0, \ + C4, C3, C2, C1, C0) \ + __asm__ ("addc %4, %14, %9\n" \ + "adde %3, %13, %8\n" \ + "adde %2, %12, %7\n" \ + "adde %1, %11, %6\n" \ + "adde %0, %10, %5\n" \ + : "=r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B4)), \ + "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C4)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB5_LIMB64(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0, \ + C4, C3, C2, C1, C0) \ + __asm__ ("subfc %4, %14, %9\n" \ + "subfe %3, %13, %8\n" \ + "subfe %2, %12, %7\n" \ + "subfe %1, %11, %6\n" \ + "subfe %0, %10, %5\n" \ + : "=r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B4)), \ + "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C4)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define ADD7_LIMB64(A6, A5, A4, A3, A2, A1, A0, B6, B5, B4, B3, B2, B1, B0, \ + C6, C5, C4, C3, C2, C1, C0) \ + __asm__ ("addc %6, %20, %13\n" \ + "adde %5, %19, %12\n" \ + "adde %4, %18, %11\n" \ + "adde %3, %17, %10\n" \ + "adde %2, %16, %9\n" \ + "adde %1, %15, %8\n" \ + "adde %0, %14, %7\n" \ + : "=r" (A6), \ + "=&r" (A5), \ + "=&r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B6)), \ + "r" ((mpi_limb_t)(B5)), \ + "r" ((mpi_limb_t)(B4)), \ + "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C6)), \ + "r" ((mpi_limb_t)(C5)), \ + "r" ((mpi_limb_t)(C4)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB7_LIMB64(A6, A5, A4, A3, A2, A1, A0, B6, B5, B4, B3, B2, B1, B0, \ + C6, C5, C4, C3, C2, C1, C0) \ + __asm__ ("subfc %6, %20, %13\n" \ + "subfe %5, %19, %12\n" \ + "subfe %4, %18, %11\n" \ + "subfe %3, %17, %10\n" \ + "subfe %2, %16, %9\n" \ + "subfe %1, %15, %8\n" \ + "subfe %0, %14, %7\n" \ + : "=r" (A6), \ + "=&r" (A5), \ + "=&r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B6)), \ + "r" ((mpi_limb_t)(B5)), \ + "r" ((mpi_limb_t)(B4)), \ + "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C6)), \ + "r" ((mpi_limb_t)(C5)), \ + "r" ((mpi_limb_t)(C4)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#endif /* __powerpc__ */ + + +/* s390x/zSeries addition/subtraction helpers. */ +#if defined (__s390x__) && defined(HAVE_CPU_ARCH_S390X) && __GNUC__ >= 4 + +#define ADD3_LIMB64(A2, A1, A0, B2, B1, B0, C2, C1, C0) \ + __asm__ ("algr %2, %8\n" \ + "alcgr %1, %7\n" \ + "alcgr %0, %6\n" \ + : "=r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B2)), \ + "1" ((mpi_limb_t)(B1)), \ + "2" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB3_LIMB64(A3, A2, A1, A0, B2, B1, B0, C2, C1, C0) \ + __asm__ ("slgr %2, %8\n" \ + "slbgr %1, %7\n" \ + "slbgr %0, %6\n" \ + : "=r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B2)), \ + "1" ((mpi_limb_t)(B1)), \ + "2" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define ADD4_LIMB64(A3, A2, A1, A0, B3, B2, B1, B0, C3, C2, C1, C0) \ + __asm__ ("algr %3, %11\n" \ + "alcgr %2, %10\n" \ + "alcgr %1, %9\n" \ + "alcgr %0, %8\n" \ + : "=r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B3)), \ + "1" ((mpi_limb_t)(B2)), \ + "2" ((mpi_limb_t)(B1)), \ + "3" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB4_LIMB64(A3, A2, A1, A0, B3, B2, B1, B0, C3, C2, C1, C0) \ + __asm__ ("slgr %3, %11\n" \ + "slbgr %2, %10\n" \ + "slbgr %1, %9\n" \ + "slbgr %0, %8\n" \ + : "=r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B3)), \ + "1" ((mpi_limb_t)(B2)), \ + "2" ((mpi_limb_t)(B1)), \ + "3" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define ADD5_LIMB64(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0, \ + C4, C3, C2, C1, C0) \ + __asm__ ("algr %4, %14\n" \ + "alcgr %3, %13\n" \ + "alcgr %2, %12\n" \ + "alcgr %1, %11\n" \ + "alcgr %0, %10\n" \ + : "=r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B4)), \ + "1" ((mpi_limb_t)(B3)), \ + "2" ((mpi_limb_t)(B2)), \ + "3" ((mpi_limb_t)(B1)), \ + "4" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C4)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB5_LIMB64(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0, \ + C4, C3, C2, C1, C0) \ + __asm__ ("slgr %4, %14\n" \ + "slbgr %3, %13\n" \ + "slbgr %2, %12\n" \ + "slbgr %1, %11\n" \ + "slbgr %0, %10\n" \ + : "=r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B4)), \ + "1" ((mpi_limb_t)(B3)), \ + "2" ((mpi_limb_t)(B2)), \ + "3" ((mpi_limb_t)(B1)), \ + "4" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C4)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define ADD7_LIMB64(A6, A5, A4, A3, A2, A1, A0, B6, B5, B4, B3, B2, B1, B0, \ + C6, C5, C4, C3, C2, C1, C0) \ + __asm__ ("algr %6, %20\n" \ + "alcgr %5, %19\n" \ + "alcgr %4, %18\n" \ + "alcgr %3, %17\n" \ + "alcgr %2, %16\n" \ + "alcgr %1, %15\n" \ + "alcgr %0, %14\n" \ + : "=r" (A6), \ + "=&r" (A5), \ + "=&r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B6)), \ + "1" ((mpi_limb_t)(B5)), \ + "2" ((mpi_limb_t)(B4)), \ + "3" ((mpi_limb_t)(B3)), \ + "4" ((mpi_limb_t)(B2)), \ + "5" ((mpi_limb_t)(B1)), \ + "6" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C6)), \ + "r" ((mpi_limb_t)(C5)), \ + "r" ((mpi_limb_t)(C4)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB7_LIMB64(A6, A5, A4, A3, A2, A1, A0, B6, B5, B4, B3, B2, B1, B0, \ + C6, C5, C4, C3, C2, C1, C0) \ + __asm__ ("slgr %6, %20\n" \ + "slbgr %5, %19\n" \ + "slbgr %4, %18\n" \ + "slbgr %3, %17\n" \ + "slbgr %2, %16\n" \ + "slbgr %1, %15\n" \ + "slbgr %0, %14\n" \ + : "=r" (A6), \ + "=&r" (A5), \ + "=&r" (A4), \ + "=&r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "0" ((mpi_limb_t)(B6)), \ + "1" ((mpi_limb_t)(B5)), \ + "2" ((mpi_limb_t)(B4)), \ + "3" ((mpi_limb_t)(B3)), \ + "4" ((mpi_limb_t)(B2)), \ + "5" ((mpi_limb_t)(B1)), \ + "6" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C6)), \ + "r" ((mpi_limb_t)(C5)), \ + "r" ((mpi_limb_t)(C4)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#endif /* __x86_64__ */ + + +/* Common 64-bit arch addition/subtraction macros. */ + +#define ADD2_LIMB64(A1, A0, B1, B0, C1, C0) \ + add_ssaaaa(A1, A0, B1, B0, C1, C0) + +#define SUB2_LIMB64(A1, A0, B1, B0, C1, C0) \ + sub_ddmmss(A1, A0, B1, B0, C1, C0) + +#endif /* BYTES_PER_MPI_LIMB == 8 */ + + +#if BYTES_PER_MPI_LIMB == 4 + +/* 64-bit limb definitions for 32-bit architectures. */ + +#define LIMBS_PER_LIMB64 2 +#define LIMB_FROM64(v) ((v).lo) +#define HIBIT_LIMB64(v) ((v).hi >> (BITS_PER_MPI_LIMB - 1)) +#define HI32_LIMB64(v) ((v).hi) +#define LO32_LIMB64(v) ((v).lo) +#define LOAD32(x, pos) ((x)[pos]) +#define LIMB64_C(hi, lo) { (lo), (hi) } + +typedef struct +{ + mpi_limb_t lo; + mpi_limb_t hi; +} mpi_limb64_t; + +static inline mpi_limb64_t +LOAD64(const mpi_ptr_t x, unsigned int pos) +{ + mpi_limb64_t v; + v.lo = x[pos * 2 + 0]; + v.hi = x[pos * 2 + 1]; + return v; +} + +static inline void +STORE64(mpi_ptr_t x, unsigned int pos, mpi_limb64_t v) +{ + x[pos * 2 + 0] = v.lo; + x[pos * 2 + 1] = v.hi; +} + +static inline void +STORE64_COND(mpi_ptr_t x, unsigned int pos, mpi_limb_t mask1, + mpi_limb64_t val1, mpi_limb_t mask2, mpi_limb64_t val2) +{ + x[pos * 2 + 0] = (mask1 & val1.lo) | (mask2 & val2.lo); + x[pos * 2 + 1] = (mask1 & val1.hi) | (mask2 & val2.hi); +} + +static inline mpi_limb64_t +LIMB_TO64(mpi_limb_t x) +{ + mpi_limb64_t v; + v.lo = x; + v.hi = 0; + return v; +} + +static inline mpi_limb64_t +LIMB64_HILO(mpi_limb_t hi, mpi_limb_t lo) +{ + mpi_limb64_t v; + v.lo = lo; + v.hi = hi; + return v; +} + + +/* i386 addition/subtraction helpers. */ +#if defined (__i386__) && defined(HAVE_CPU_ARCH_X86) && __GNUC__ >= 4 + +#define ADD4_LIMB32(a3, a2, a1, a0, b3, b2, b1, b0, c3, c2, c1, c0) \ + __asm__ ("addl %11, %3\n" \ + "adcl %10, %2\n" \ + "adcl %9, %1\n" \ + "adcl %8, %0\n" \ + : "=r" (a3), \ + "=&r" (a2), \ + "=&r" (a1), \ + "=&r" (a0) \ + : "0" ((mpi_limb_t)(b3)), \ + "1" ((mpi_limb_t)(b2)), \ + "2" ((mpi_limb_t)(b1)), \ + "3" ((mpi_limb_t)(b0)), \ + "g" ((mpi_limb_t)(c3)), \ + "g" ((mpi_limb_t)(c2)), \ + "g" ((mpi_limb_t)(c1)), \ + "g" ((mpi_limb_t)(c0)) \ + : "cc") + +#define SUB4_LIMB32(a3, a2, a1, a0, b3, b2, b1, b0, c3, c2, c1, c0) \ + __asm__ ("subl %11, %3\n" \ + "sbbl %10, %2\n" \ + "sbbl %9, %1\n" \ + "sbbl %8, %0\n" \ + : "=r" (a3), \ + "=&r" (a2), \ + "=&r" (a1), \ + "=&r" (a0) \ + : "0" ((mpi_limb_t)(b3)), \ + "1" ((mpi_limb_t)(b2)), \ + "2" ((mpi_limb_t)(b1)), \ + "3" ((mpi_limb_t)(b0)), \ + "g" ((mpi_limb_t)(c3)), \ + "g" ((mpi_limb_t)(c2)), \ + "g" ((mpi_limb_t)(c1)), \ + "g" ((mpi_limb_t)(c0)) \ + : "cc") + +#endif /* __i386__ */ + + +/* ARM addition/subtraction helpers. */ +#ifdef HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS + +#define ADD4_LIMB32(A3, A2, A1, A0, B3, B2, B1, B0, C3, C2, C1, C0) \ + __asm__ ("adds %3, %7, %11\n" \ + "adcs %2, %6, %10\n" \ + "adcs %1, %5, %9\n" \ + "adc %0, %4, %8\n" \ + : "=r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#define SUB4_LIMB32(A3, A2, A1, A0, B3, B2, B1, B0, C3, C2, C1, C0) \ + __asm__ ("subs %3, %7, %11\n" \ + "sbcs %2, %6, %10\n" \ + "sbcs %1, %5, %9\n" \ + "sbc %0, %4, %8\n" \ + : "=r" (A3), \ + "=&r" (A2), \ + "=&r" (A1), \ + "=&r" (A0) \ + : "r" ((mpi_limb_t)(B3)), \ + "r" ((mpi_limb_t)(B2)), \ + "r" ((mpi_limb_t)(B1)), \ + "r" ((mpi_limb_t)(B0)), \ + "r" ((mpi_limb_t)(C3)), \ + "r" ((mpi_limb_t)(C2)), \ + "r" ((mpi_limb_t)(C1)), \ + "r" ((mpi_limb_t)(C0)) \ + : "cc") + +#endif /* HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS */ + + +/* Common 32-bit arch addition/subtraction macros. */ + +#if defined(ADD4_LIMB32) +/* A[0..1] = B[0..1] + C[0..1] */ +#define ADD2_LIMB64(A1, A0, B1, B0, C1, C0) \ + ADD4_LIMB32(A1.hi, A1.lo, A0.hi, A0.lo, \ + B1.hi, B1.lo, B0.hi, B0.lo, \ + C1.hi, C1.lo, C0.hi, C0.lo) +#else +/* A[0..1] = B[0..1] + C[0..1] */ +#define ADD2_LIMB64(A1, A0, B1, B0, C1, C0) do { \ + mpi_limb_t __carry2_0, __carry2_1; \ + add_ssaaaa(__carry2_0, A0.lo, 0, B0.lo, 0, C0.lo); \ + add_ssaaaa(__carry2_1, A0.hi, 0, B0.hi, 0, C0.hi); \ + add_ssaaaa(__carry2_1, A0.hi, __carry2_1, A0.hi, 0, __carry2_0); \ + add_ssaaaa(A1.hi, A1.lo, B1.hi, B1.lo, C1.hi, C1.lo); \ + add_ssaaaa(A1.hi, A1.lo, A1.hi, A1.lo, 0, __carry2_1); \ + } while (0) +#endif + +#if defined(SUB4_LIMB32) +/* A[0..1] = B[0..1] - C[0..1] */ +#define SUB2_LIMB64(A1, A0, B1, B0, C1, C0) \ + SUB4_LIMB32(A1.hi, A1.lo, A0.hi, A0.lo, \ + B1.hi, B1.lo, B0.hi, B0.lo, \ + C1.hi, C1.lo, C0.hi, C0.lo) +#else +/* A[0..1] = B[0..1] - C[0..1] */ +#define SUB2_LIMB64(A1, A0, B1, B0, C1, C0) do { \ + mpi_limb_t __borrow2_0, __borrow2_1; \ + sub_ddmmss(__borrow2_0, A0.lo, 0, B0.lo, 0, C0.lo); \ + sub_ddmmss(__borrow2_1, A0.hi, 0, B0.hi, 0, C0.hi); \ + sub_ddmmss(__borrow2_1, A0.hi, __borrow2_1, A0.hi, 0, -__borrow2_0); \ + sub_ddmmss(A1.hi, A1.lo, B1.hi, B1.lo, C1.hi, C1.lo); \ + sub_ddmmss(A1.hi, A1.lo, A1.hi, A1.lo, 0, -__borrow2_1); \ + } while (0) +#endif + +#endif /* BYTES_PER_MPI_LIMB == 4 */ + + +/* Common definitions. */ +#define BITS_PER_MPI_LIMB64 (BITS_PER_MPI_LIMB * LIMBS_PER_LIMB64) +#define BYTES_PER_MPI_LIMB64 (BYTES_PER_MPI_LIMB * LIMBS_PER_LIMB64) + + +/* Common addition/subtraction macros. */ + +#ifndef ADD3_LIMB64 +/* A[0..2] = B[0..2] + C[0..2] */ +#define ADD3_LIMB64(A2, A1, A0, B2, B1, B0, C2, C1, C0) do { \ + mpi_limb64_t __carry3; \ + ADD2_LIMB64(__carry3, A0, zero, B0, zero, C0); \ + ADD2_LIMB64(A2, A1, B2, B1, C2, C1); \ + ADD2_LIMB64(A2, A1, A2, A1, zero, __carry3); \ + } while (0) +#endif + +#ifndef ADD4_LIMB64 +/* A[0..3] = B[0..3] + C[0..3] */ +#define ADD4_LIMB64(A3, A2, A1, A0, B3, B2, B1, B0, C3, C2, C1, C0) do { \ + mpi_limb64_t __carry4; \ + ADD3_LIMB64(__carry4, A1, A0, zero, B1, B0, zero, C1, C0); \ + ADD2_LIMB64(A3, A2, B3, B2, C3, C2); \ + ADD2_LIMB64(A3, A2, A3, A2, zero, __carry4); \ + } while (0) +#endif + +#ifndef ADD5_LIMB64 +/* A[0..4] = B[0..4] + C[0..4] */ +#define ADD5_LIMB64(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0, \ + C4, C3, C2, C1, C0) do { \ + mpi_limb64_t __carry5; \ + ADD4_LIMB64(__carry5, A2, A1, A0, zero, B2, B1, B0, zero, C2, C1, C0); \ + ADD2_LIMB64(A4, A3, B4, B3, C4, C3); \ + ADD2_LIMB64(A4, A3, A4, A3, zero, __carry5); \ + } while (0) +#endif + +#ifndef ADD6_LIMB64 +/* A[0..5] = B[0..5] + C[0..5] */ +#define ADD6_LIMB64(A5, A4, A3, A2, A1, A0, B5, B4, B3, B2, B1, B0, \ + C5, C4, C3, C2, C1, C0) do { \ + mpi_limb64_t __carry6; \ + ADD5_LIMB64(__carry6, A3, A2, A1, A0, zero, B3, B2, B1, B0, \ + zero, C3, C2, C1, C0); \ + ADD2_LIMB64(A5, A4, B5, B4, C5, C4); \ + ADD2_LIMB64(A5, A4, A5, A4, zero, __carry6); \ + } while (0) +#endif + +#ifndef ADD7_LIMB64 +/* A[0..6] = B[0..6] + C[0..6] */ +#define ADD7_LIMB64(A6, A5, A4, A3, A2, A1, A0, B6, B5, B4, B3, B2, B1, B0, \ + C6, C5, C4, C3, C2, C1, C0) do { \ + mpi_limb64_t __carry7; \ + ADD6_LIMB64(__carry7, A4, A3, A2, A1, A0, zero, B4, B3, B2, B1, B0, \ + zero, C4, C3, C2, C1, C0); \ + ADD2_LIMB64(A6, A5, B6, B5, C6, C5); \ + ADD2_LIMB64(A6, A5, A6, A5, zero, __carry7); \ + } while (0) +#endif + +#ifndef SUB3_LIMB64 +/* A[0..2] = B[0..2] - C[0..2] */ +#define SUB3_LIMB64(A2, A1, A0, B2, B1, B0, C2, C1, C0) do { \ + mpi_limb64_t __borrow3; \ + SUB2_LIMB64(__borrow3, A0, zero, B0, zero, C0); \ + SUB2_LIMB64(A2, A1, B2, B1, C2, C1); \ + SUB2_LIMB64(A2, A1, A2, A1, zero, LIMB_TO64(-LIMB_FROM64(__borrow3))); \ + } while (0) +#endif + +#ifndef SUB4_LIMB64 +/* A[0..3] = B[0..3] - C[0..3] */ +#define SUB4_LIMB64(A3, A2, A1, A0, B3, B2, B1, B0, C3, C2, C1, C0) do { \ + mpi_limb64_t __borrow4; \ + SUB3_LIMB64(__borrow4, A1, A0, zero, B1, B0, zero, C1, C0); \ + SUB2_LIMB64(A3, A2, B3, B2, C3, C2); \ + SUB2_LIMB64(A3, A2, A3, A2, zero, LIMB_TO64(-LIMB_FROM64(__borrow4))); \ + } while (0) +#endif + +#ifndef SUB5_LIMB64 +/* A[0..4] = B[0..4] - C[0..4] */ +#define SUB5_LIMB64(A4, A3, A2, A1, A0, B4, B3, B2, B1, B0, \ + C4, C3, C2, C1, C0) do { \ + mpi_limb64_t __borrow5; \ + SUB4_LIMB64(__borrow5, A2, A1, A0, zero, B2, B1, B0, zero, C2, C1, C0); \ + SUB2_LIMB64(A4, A3, B4, B3, C4, C3); \ + SUB2_LIMB64(A4, A3, A4, A3, zero, LIMB_TO64(-LIMB_FROM64(__borrow5))); \ + } while (0) +#endif + +#ifndef SUB6_LIMB64 +/* A[0..5] = B[0..5] - C[0..5] */ +#define SUB6_LIMB64(A5, A4, A3, A2, A1, A0, B5, B4, B3, B2, B1, B0, \ + C5, C4, C3, C2, C1, C0) do { \ + mpi_limb64_t __borrow6; \ + SUB5_LIMB64(__borrow6, A3, A2, A1, A0, zero, B3, B2, B1, B0, \ + zero, C3, C2, C1, C0); \ + SUB2_LIMB64(A5, A4, B5, B4, C5, C4); \ + SUB2_LIMB64(A5, A4, A5, A4, zero, LIMB_TO64(-LIMB_FROM64(__borrow6))); \ + } while (0) +#endif + +#ifndef SUB7_LIMB64 +/* A[0..6] = B[0..6] - C[0..6] */ +#define SUB7_LIMB64(A6, A5, A4, A3, A2, A1, A0, B6, B5, B4, B3, B2, B1, B0, \ + C6, C5, C4, C3, C2, C1, C0) do { \ + mpi_limb64_t __borrow7; \ + SUB6_LIMB64(__borrow7, A4, A3, A2, A1, A0, zero, B4, B3, B2, B1, B0, \ + zero, C4, C3, C2, C1, C0); \ + SUB2_LIMB64(A6, A5, B6, B5, C6, C5); \ + SUB2_LIMB64(A6, A5, A6, A5, zero, LIMB_TO64(-LIMB_FROM64(__borrow7))); \ + } while (0) +#endif + + +/* Helper functions. */ + +static inline int +mpi_nbits_more_than (gcry_mpi_t w, unsigned int nbits) +{ + unsigned int nbits_nlimbs; + mpi_limb_t wlimb; + unsigned int n; + + nbits_nlimbs = (nbits + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB; + + /* Note: Assumes that 'w' is normalized. */ + + if (w->nlimbs > nbits_nlimbs) + return 1; + if (w->nlimbs < nbits_nlimbs) + return 0; + if ((nbits % BITS_PER_MPI_LIMB) == 0) + return 0; + + wlimb = w->d[nbits_nlimbs - 1]; + if (wlimb == 0) + log_bug ("mpi_nbits_more_than: input mpi not normalized\n"); + + count_leading_zeros (n, wlimb); + + return (BITS_PER_MPI_LIMB - n) > (nbits % BITS_PER_MPI_LIMB); +} + +#endif /* GCRY_EC_INLINE_H */ diff --git a/mpi/ec-internal.h b/mpi/ec-internal.h index 759335aa..2296d55d 100644 --- a/mpi/ec-internal.h +++ b/mpi/ec-internal.h @@ -20,6 +20,22 @@ #ifndef GCRY_EC_INTERNAL_H #define GCRY_EC_INTERNAL_H +#include + void _gcry_mpi_ec_ed25519_mod (gcry_mpi_t a); +#ifndef ASM_DISABLED +void _gcry_mpi_ec_nist192_mod (gcry_mpi_t w, mpi_ec_t ctx); +void _gcry_mpi_ec_nist224_mod (gcry_mpi_t w, mpi_ec_t ctx); +void _gcry_mpi_ec_nist256_mod (gcry_mpi_t w, mpi_ec_t ctx); +void _gcry_mpi_ec_nist384_mod (gcry_mpi_t w, mpi_ec_t ctx); +void _gcry_mpi_ec_nist521_mod (gcry_mpi_t w, mpi_ec_t ctx); +#else +# define _gcry_mpi_ec_nist192_mod NULL +# define _gcry_mpi_ec_nist224_mod NULL +# define _gcry_mpi_ec_nist256_mod NULL +# define _gcry_mpi_ec_nist384_mod NULL +# define _gcry_mpi_ec_nist521_mod NULL +#endif + #endif /*GCRY_EC_INTERNAL_H*/ diff --git a/mpi/ec-nist.c b/mpi/ec-nist.c new file mode 100644 index 00000000..1a8281be --- /dev/null +++ b/mpi/ec-nist.c @@ -0,0 +1,787 @@ +/* ec-nist.c - NIST optimized elliptic curve functions + * Copyright (C) 2021 Jussi Kivilinna + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include + + +#ifndef ASM_DISABLED + + +#include "mpi-internal.h" +#include "longlong.h" +#include "g10lib.h" +#include "context.h" +#include "ec-context.h" +#include "ec-inline.h" + + +/* These variables are used to generate masks from conditional operation + * flag parameters. Use of volatile prevents compiler optimizations from + * converting AND-masking to conditional branches. */ +static volatile mpi_limb_t vzero = 0; +static volatile mpi_limb_t vone = 1; + + +static inline +void prefetch(const void *tab, size_t len) +{ + const volatile byte *vtab = tab; + + if (len > 0 * 64) + (void)vtab[0 * 64]; + if (len > 1 * 64) + (void)vtab[1 * 64]; + if (len > 2 * 64) + (void)vtab[2 * 64]; + if (len > 3 * 64) + (void)vtab[3 * 64]; + if (len > 4 * 64) + (void)vtab[4 * 64]; + if (len > 5 * 64) + (void)vtab[5 * 64]; + if (len > 6 * 64) + (void)vtab[6 * 64]; + if (len > 7 * 64) + (void)vtab[7 * 64]; + if (len > 8 * 64) + (void)vtab[8 * 64]; + if (len > 9 * 64) + (void)vtab[9 * 64]; + if (len > 10 * 64) + (void)vtab[10 * 64]; + (void)vtab[len - 1]; +} + + +/* Fast reduction routines for NIST curves. */ + +void +_gcry_mpi_ec_nist192_mod (gcry_mpi_t w, mpi_ec_t ctx) +{ + static const mpi_limb64_t p_mult[3][4] = + { + { /* P * 1 */ + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0xffffffffU, 0xfffffffeU), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0x00000000U, 0x00000000U) + }, + { /* P * 2 */ + LIMB64_C(0xffffffffU, 0xfffffffeU), LIMB64_C(0xffffffffU, 0xfffffffdU), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0x00000000U, 0x00000001U) + }, + { /* P * 3 */ + LIMB64_C(0xffffffffU, 0xfffffffdU), LIMB64_C(0xffffffffU, 0xfffffffcU), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0x00000000U, 0x00000002U) + } + }; + const mpi_limb64_t zero = LIMB_TO64(0); + mpi_ptr_t wp; + mpi_ptr_t pp; + mpi_size_t wsize = 192 / BITS_PER_MPI_LIMB64; + mpi_limb64_t s[wsize + 1]; + mpi_limb64_t o[wsize + 1]; + mpi_limb_t mask1; + mpi_limb_t mask2; + int carry; + + MPN_NORMALIZE (w->d, w->nlimbs); + if (mpi_nbits_more_than (w, 2 * 192)) + log_bug ("W must be less than m^2\n"); + + RESIZE_AND_CLEAR_IF_NEEDED (w, wsize * 2 * LIMBS_PER_LIMB64); + RESIZE_AND_CLEAR_IF_NEEDED (ctx->p, wsize * LIMBS_PER_LIMB64); + + pp = ctx->p->d; + wp = w->d; + + prefetch (p_mult, sizeof(p_mult)); + + /* See "FIPS 186-4, D.2.1 Curve P-192". */ + + s[0] = LOAD64(wp, 3); + ADD3_LIMB64 (s[3], s[2], s[1], + zero, zero, LOAD64(wp, 3), + zero, LOAD64(wp, 4), LOAD64(wp, 4)); + + ADD4_LIMB64 (s[3], s[2], s[1], s[0], + s[3], s[2], s[1], s[0], + zero, LOAD64(wp, 5), LOAD64(wp, 5), LOAD64(wp, 5)); + + ADD4_LIMB64 (s[3], s[2], s[1], s[0], + s[3], s[2], s[1], s[0], + zero, LOAD64(wp, 2), LOAD64(wp, 1), LOAD64(wp, 0)); + + /* mod p: + * 's[3]' holds carry value (0..2). Subtract (carry + 1) * p. Result will be + * with in range -p...p. Handle result being negative with addition and + * conditional store. */ + + carry = LO32_LIMB64(s[3]); + + SUB4_LIMB64 (s[3], s[2], s[1], s[0], + s[3], s[2], s[1], s[0], + p_mult[carry][3], p_mult[carry][2], + p_mult[carry][1], p_mult[carry][0]); + + ADD4_LIMB64 (o[3], o[2], o[1], o[0], + s[3], s[2], s[1], s[0], + zero, LOAD64(pp, 2), LOAD64(pp, 1), LOAD64(pp, 0)); + mask1 = vzero - (LO32_LIMB64(o[3]) >> 31); + mask2 = (LO32_LIMB64(o[3]) >> 31) - vone; + + STORE64_COND(wp, 0, mask2, o[0], mask1, s[0]); + STORE64_COND(wp, 1, mask2, o[1], mask1, s[1]); + STORE64_COND(wp, 2, mask2, o[2], mask1, s[2]); + + w->nlimbs = 192 / BITS_PER_MPI_LIMB; + MPN_NORMALIZE (wp, w->nlimbs); +} + +void +_gcry_mpi_ec_nist224_mod (gcry_mpi_t w, mpi_ec_t ctx) +{ + static const mpi_limb64_t p_mult[5][4] = + { + { /* P * -1 */ + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0x00000000U, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0xffffffffU, 0x00000000U) + }, + { /* P * 0 */ + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0x00000000U, 0x00000000U), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0x00000000U, 0x00000000U) + }, + { /* P * 1 */ + LIMB64_C(0x00000000U, 0x00000001U), LIMB64_C(0xffffffffU, 0x00000000U), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0x00000000U, 0xffffffffU) + }, + { /* P * 2 */ + LIMB64_C(0x00000000U, 0x00000002U), LIMB64_C(0xfffffffeU, 0x00000000U), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0x00000001U, 0xffffffffU) + }, + { /* P * 3 */ + LIMB64_C(0x00000000U, 0x00000003U), LIMB64_C(0xfffffffdU, 0x00000000U), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0x00000002U, 0xffffffffU) + } + }; + const mpi_limb64_t zero = LIMB_TO64(0); + mpi_ptr_t wp; + mpi_ptr_t pp; + mpi_size_t wsize = (224 + BITS_PER_MPI_LIMB64 - 1) / BITS_PER_MPI_LIMB64; + mpi_size_t psize = ctx->p->nlimbs; + mpi_limb64_t s[wsize]; + mpi_limb64_t d[wsize]; + mpi_limb_t mask1; + mpi_limb_t mask2; + int carry; + + MPN_NORMALIZE (w->d, w->nlimbs); + if (mpi_nbits_more_than (w, 2 * 224)) + log_bug ("W must be less than m^2\n"); + + RESIZE_AND_CLEAR_IF_NEEDED (w, wsize * 2 * LIMBS_PER_LIMB64); + RESIZE_AND_CLEAR_IF_NEEDED (ctx->p, wsize * LIMBS_PER_LIMB64); + ctx->p->nlimbs = psize; + + pp = ctx->p->d; + wp = w->d; + + prefetch (p_mult, sizeof(p_mult)); + + /* See "FIPS 186-4, D.2.2 Curve P-224". */ + + /* "S1 + S2" with 64-bit limbs: + * [0:A10]:[ A9: A8]:[ A7:0]:[0:0] + * + [0:0]:[A13:A12]:[A11:0]:[0:0] + * => s[3]:s[2]:s[1]:s[0] + */ + s[0] = zero; + ADD3_LIMB64 (s[3], s[2], s[1], + LIMB64_HILO(0, LOAD32(wp, 10)), + LOAD64(wp, 8 / 2), + LIMB64_HILO(LOAD32(wp, 7), 0), + zero, + LOAD64(wp, 12 / 2), + LIMB64_HILO(LOAD32(wp, 11), 0)); + + /* "T + S1 + S2" */ + ADD4_LIMB64 (s[3], s[2], s[1], s[0], + s[3], s[2], s[1], s[0], + LIMB64_HILO(0, LOAD32(wp, 6)), + LOAD64(wp, 4 / 2), + LOAD64(wp, 2 / 2), + LOAD64(wp, 0 / 2)); + + /* "D1 + D2" with 64-bit limbs: + * [0:A13]:[A12:A11]:[A10: A9]:[ A8: A7] + * + [0:0]:[ 0: 0]:[ 0:A13]:[A12:A11] + * => d[3]:d[2]:d[1]:d[0] + */ + ADD4_LIMB64 (d[3], d[2], d[1], d[0], + LIMB64_HILO(0, LOAD32(wp, 13)), + LIMB64_HILO(LOAD32(wp, 12), LOAD32(wp, 11)), + LIMB64_HILO(LOAD32(wp, 10), LOAD32(wp, 9)), + LIMB64_HILO(LOAD32(wp, 8), LOAD32(wp, 7)), + zero, + zero, + LIMB64_HILO(0, LOAD32(wp, 13)), + LIMB64_HILO(LOAD32(wp, 12), LOAD32(wp, 11))); + + /* "T + S1 + S2 - D1 - D2" */ + SUB4_LIMB64 (s[3], s[2], s[1], s[0], + s[3], s[2], s[1], s[0], + d[3], d[2], d[1], d[0]); + + /* mod p: + * Upper 32-bits of 's[3]' holds carry value (-2..2). + * Subtract (carry + 1) * p. Result will be with in range -p...p. + * Handle result being negative with addition and conditional store. */ + + carry = HI32_LIMB64(s[3]); + + SUB4_LIMB64 (s[3], s[2], s[1], s[0], + s[3], s[2], s[1], s[0], + p_mult[carry + 2][3], p_mult[carry + 2][2], + p_mult[carry + 2][1], p_mult[carry + 2][0]); + + ADD4_LIMB64 (d[3], d[2], d[1], d[0], + s[3], s[2], s[1], s[0], + LOAD64(pp, 3), LOAD64(pp, 2), LOAD64(pp, 1), LOAD64(pp, 0)); + + mask1 = vzero - (HI32_LIMB64(d[3]) >> 31); + mask2 = (HI32_LIMB64(d[3]) >> 31) - vone; + + STORE64_COND(wp, 0, mask2, d[0], mask1, s[0]); + STORE64_COND(wp, 1, mask2, d[1], mask1, s[1]); + STORE64_COND(wp, 2, mask2, d[2], mask1, s[2]); + STORE64_COND(wp, 3, mask2, d[3], mask1, s[3]); + + w->nlimbs = wsize * LIMBS_PER_LIMB64; + MPN_NORMALIZE (wp, w->nlimbs); +} + +void +_gcry_mpi_ec_nist256_mod (gcry_mpi_t w, mpi_ec_t ctx) +{ + static const mpi_limb64_t p_mult[11][5] = + { + { /* P * -3 */ + LIMB64_C(0x00000000U, 0x00000003U), LIMB64_C(0xfffffffdU, 0x00000000U), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0x00000002U, 0xfffffffcU), + LIMB64_C(0xffffffffU, 0xfffffffdU) + }, + { /* P * -2 */ + LIMB64_C(0x00000000U, 0x00000002U), LIMB64_C(0xfffffffeU, 0x00000000U), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0x00000001U, 0xfffffffdU), + LIMB64_C(0xffffffffU, 0xfffffffeU) + }, + { /* P * -1 */ + LIMB64_C(0x00000000U, 0x00000001U), LIMB64_C(0xffffffffU, 0x00000000U), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0x00000000U, 0xfffffffeU), + LIMB64_C(0xffffffffU, 0xffffffffU) + }, + { /* P * 0 */ + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0x00000000U, 0x00000000U), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0x00000000U, 0x00000000U), + LIMB64_C(0x00000000U, 0x00000000U) + }, + { /* P * 1 */ + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0x00000000U, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0xffffffffU, 0x00000001U), + LIMB64_C(0x00000000U, 0x00000000U) + }, + { /* P * 2 */ + LIMB64_C(0xffffffffU, 0xfffffffeU), LIMB64_C(0x00000001U, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0xfffffffeU, 0x00000002U), + LIMB64_C(0x00000000U, 0x00000001U) + }, + { /* P * 3 */ + LIMB64_C(0xffffffffU, 0xfffffffdU), LIMB64_C(0x00000002U, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0xfffffffdU, 0x00000003U), + LIMB64_C(0x00000000U, 0x00000002U) + }, + { /* P * 4 */ + LIMB64_C(0xffffffffU, 0xfffffffcU), LIMB64_C(0x00000003U, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0xfffffffcU, 0x00000004U), + LIMB64_C(0x00000000U, 0x00000003U) + }, + { /* P * 5 */ + LIMB64_C(0xffffffffU, 0xfffffffbU), LIMB64_C(0x00000004U, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0xfffffffbU, 0x00000005U), + LIMB64_C(0x00000000U, 0x00000004U) + }, + { /* P * 6 */ + LIMB64_C(0xffffffffU, 0xfffffffaU), LIMB64_C(0x00000005U, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0xfffffffaU, 0x00000006U), + LIMB64_C(0x00000000U, 0x00000005U) + }, + { /* P * 7 */ + LIMB64_C(0xffffffffU, 0xfffffff9U), LIMB64_C(0x00000006U, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0xfffffff9U, 0x00000007U), + LIMB64_C(0x00000000U, 0x00000006U) + } + }; + const mpi_limb64_t zero = LIMB_TO64(0); + mpi_ptr_t wp; + mpi_ptr_t pp; + mpi_size_t wsize = (256 + BITS_PER_MPI_LIMB64 - 1) / BITS_PER_MPI_LIMB64; + mpi_size_t psize = ctx->p->nlimbs; + mpi_limb64_t s[wsize + 1]; + mpi_limb64_t t[wsize + 1]; + mpi_limb64_t d[wsize + 1]; + mpi_limb_t mask1; + mpi_limb_t mask2; + int carry; + + MPN_NORMALIZE (w->d, w->nlimbs); + if (mpi_nbits_more_than (w, 2 * 256)) + log_bug ("W must be less than m^2\n"); + + RESIZE_AND_CLEAR_IF_NEEDED (w, wsize * 2 * LIMBS_PER_LIMB64); + RESIZE_AND_CLEAR_IF_NEEDED (ctx->p, wsize * LIMBS_PER_LIMB64); + ctx->p->nlimbs = psize; + + pp = ctx->p->d; + wp = w->d; + + prefetch (p_mult, sizeof(p_mult)); + + /* See "FIPS 186-4, D.2.3 Curve P-256". */ + + /* "S1 + S2" with 64-bit limbs: + * [A15:A14]:[A13:A12]:[A11:0]:[0:0] + * + [0:A15]:[A14:A13]:[A12:0]:[0:0] + * => s[4]:s[3]:s[2]:s[1]:s[0] + */ + s[0] = zero; + ADD4_LIMB64 (s[4], s[3], s[2], s[1], + zero, + LOAD64(wp, 14 / 2), + LOAD64(wp, 12 / 2), + LIMB64_HILO(LOAD32(wp, 11), 0), + zero, + LIMB64_HILO(0, LOAD32(wp, 15)), + LIMB64_HILO(LOAD32(wp, 14), LOAD32(wp, 13)), + LIMB64_HILO(LOAD32(wp, 12), 0)); + + /* "S3 + S4" with 64-bit limbs: + * [A15:A14]:[ 0: 0]:[ 0:A10]:[ A9:A8] + * + [A8:A13]:[A15:A14]:[A13:A11]:[A10:A9] + * => t[4]:t[3]:t[2]:t[1]:t[0] + */ + ADD5_LIMB64 (t[4], t[3], t[2], t[1], t[0], + zero, + LOAD64(wp, 14 / 2), + zero, + LIMB64_HILO(0, LOAD32(wp, 10)), + LOAD64(wp, 8 / 2), + zero, + LIMB64_HILO(LOAD32(wp, 8), LOAD32(wp, 13)), + LOAD64(wp, 14 / 2), + LIMB64_HILO(LOAD32(wp, 13), LOAD32(wp, 11)), + LIMB64_HILO(LOAD32(wp, 10), LOAD32(wp, 9))); + + /* "2*S1 + 2*S2" */ + ADD5_LIMB64 (s[4], s[3], s[2], s[1], s[0], + s[4], s[3], s[2], s[1], s[0], + s[4], s[3], s[2], s[1], s[0]); + + /* "D1 + D2" with 64-bit limbs: + * [0:A13]:[A12:A11] + [A15:A14]:[A13:A12] => d[2]:d[1]:d[0] + * [A10:A8] + [A11:A9] => d[4]:d[3] + */ + ADD3_LIMB64 (d[2], d[1], d[0], + zero, + LIMB64_HILO(0, LOAD32(wp, 13)), + LIMB64_HILO(LOAD32(wp, 12), LOAD32(wp, 11)), + zero, + LOAD64(wp, 14 / 2), + LOAD64(wp, 12 / 2)); + ADD2_LIMB64 (d[4], d[3], + zero, LIMB64_HILO(LOAD32(wp, 10), LOAD32(wp, 8)), + zero, LIMB64_HILO(LOAD32(wp, 11), LOAD32(wp, 9))); + + /* "T + S3 + S4" */ + ADD5_LIMB64 (t[4], t[3], t[2], t[1], t[0], + t[4], t[3], t[2], t[1], t[0], + zero, + LOAD64(wp, 6 / 2), + LOAD64(wp, 4 / 2), + LOAD64(wp, 2 / 2), + LOAD64(wp, 0 / 2)); + + /* "2*S1 + 2*S2 - D3" with 64-bit limbs: + * s[4]: s[3]: s[2]: s[1]: s[0] + * - [A12:0]:[A10:A9]:[A8:A15]:[A14:A13] + * => s[4]:s[3]:s[2]:s[1]:s[0] + */ + SUB5_LIMB64 (s[4], s[3], s[2], s[1], s[0], + s[4], s[3], s[2], s[1], s[0], + zero, + LIMB64_HILO(LOAD32(wp, 12), 0), + LIMB64_HILO(LOAD32(wp, 10), LOAD32(wp, 9)), + LIMB64_HILO(LOAD32(wp, 8), LOAD32(wp, 15)), + LIMB64_HILO(LOAD32(wp, 14), LOAD32(wp, 13))); + + /* "D1 + D2 + D4" with 64-bit limbs: + * d[4]: d[3]: d[2]: d[1]: d[0] + * - [A13:0]:[A11:A10]:[A9:0]:[A15:A14] + * => d[4]:d[3]:d[2]:d[1]:d[0] + */ + ADD5_LIMB64 (d[4], d[3], d[2], d[1], d[0], + d[4], d[3], d[2], d[1], d[0], + zero, + LIMB64_HILO(LOAD32(wp, 13), 0), + LOAD64(wp, 10 / 2), + LIMB64_HILO(LOAD32(wp, 9), 0), + LOAD64(wp, 14 / 2)); + + /* "T + 2*S1 + 2*S2 + S3 + S4 - D3" */ + ADD5_LIMB64 (s[4], s[3], s[2], s[1], s[0], + s[4], s[3], s[2], s[1], s[0], + t[4], t[3], t[2], t[1], t[0]); + + /* "T + 2*S1 + 2*S2 + S3 + S4 - D1 - D2 - D3 - D4" */ + SUB5_LIMB64 (s[4], s[3], s[2], s[1], s[0], + s[4], s[3], s[2], s[1], s[0], + d[4], d[3], d[2], d[1], d[0]); + + /* mod p: + * 's[4]' holds carry value (-4..6). Subtract (carry + 1) * p. Result + * will be with in range -p...p. Handle result being negative with + * addition and conditional store. */ + + carry = LO32_LIMB64(s[4]); + + SUB5_LIMB64 (s[4], s[3], s[2], s[1], s[0], + s[4], s[3], s[2], s[1], s[0], + p_mult[carry + 4][4], p_mult[carry + 4][3], + p_mult[carry + 4][2], p_mult[carry + 4][1], + p_mult[carry + 4][0]); + + ADD5_LIMB64 (d[4], d[3], d[2], d[1], d[0], + s[4], s[3], s[2], s[1], s[0], + zero, + LOAD64(pp, 3), LOAD64(pp, 2), LOAD64(pp, 1), LOAD64(pp, 0)); + + mask1 = vzero - (LO32_LIMB64(d[4]) >> 31); + mask2 = (LO32_LIMB64(d[4]) >> 31) - vone; + + STORE64_COND(wp, 0, mask2, d[0], mask1, s[0]); + STORE64_COND(wp, 1, mask2, d[1], mask1, s[1]); + STORE64_COND(wp, 2, mask2, d[2], mask1, s[2]); + STORE64_COND(wp, 3, mask2, d[3], mask1, s[3]); + + w->nlimbs = wsize * LIMBS_PER_LIMB64; + MPN_NORMALIZE (wp, w->nlimbs); +} + +void +_gcry_mpi_ec_nist384_mod (gcry_mpi_t w, mpi_ec_t ctx) +{ + static const mpi_limb64_t p_mult[11][7] = + { + { /* P * -2 */ + LIMB64_C(0xfffffffeU, 0x00000002U), LIMB64_C(0x00000001U, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000002U), LIMB64_C(0x00000000U, 0x00000000U), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0x00000000U, 0x00000000U), + LIMB64_C(0xffffffffU, 0xfffffffeU) + }, + { /* P * -1 */ + LIMB64_C(0xffffffffU, 0x00000001U), LIMB64_C(0x00000000U, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000001U), LIMB64_C(0x00000000U, 0x00000000U), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0x00000000U, 0x00000000U), + LIMB64_C(0xffffffffU, 0xffffffffU) + }, + { /* P * 0 */ + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0x00000000U, 0x00000000U), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0x00000000U, 0x00000000U), + LIMB64_C(0x00000000U, 0x00000000U), LIMB64_C(0x00000000U, 0x00000000U), + LIMB64_C(0x00000000U, 0x00000000U) + }, + { /* P * 1 */ + LIMB64_C(0x00000000U, 0xffffffffU), LIMB64_C(0xffffffffU, 0x00000000U), + LIMB64_C(0xffffffffU, 0xfffffffeU), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000000U) + }, + { /* P * 2 */ + LIMB64_C(0x00000001U, 0xfffffffeU), LIMB64_C(0xfffffffeU, 0x00000000U), + LIMB64_C(0xffffffffU, 0xfffffffdU), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000001U) + }, + { /* P * 3 */ + LIMB64_C(0x00000002U, 0xfffffffdU), LIMB64_C(0xfffffffdU, 0x00000000U), + LIMB64_C(0xffffffffU, 0xfffffffcU), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000002U) + }, + { /* P * 4 */ + LIMB64_C(0x00000003U, 0xfffffffcU), LIMB64_C(0xfffffffcU, 0x00000000U), + LIMB64_C(0xffffffffU, 0xfffffffbU), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000003U) + }, + { /* P * 5 */ + LIMB64_C(0x00000004U, 0xfffffffbU), LIMB64_C(0xfffffffbU, 0x00000000U), + LIMB64_C(0xffffffffU, 0xfffffffaU), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000004U) + }, + { /* P * 6 */ + LIMB64_C(0x00000005U, 0xfffffffaU), LIMB64_C(0xfffffffaU, 0x00000000U), + LIMB64_C(0xffffffffU, 0xfffffff9U), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000005U) + }, + { /* P * 7 */ + LIMB64_C(0x00000006U, 0xfffffff9U), LIMB64_C(0xfffffff9U, 0x00000000U), + LIMB64_C(0xffffffffU, 0xfffffff8U), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000006U) + }, + { /* P * 8 */ + LIMB64_C(0x00000007U, 0xfffffff8U), LIMB64_C(0xfffffff8U, 0x00000000U), + LIMB64_C(0xffffffffU, 0xfffffff7U), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0xffffffffU, 0xffffffffU), LIMB64_C(0xffffffffU, 0xffffffffU), + LIMB64_C(0x00000000U, 0x00000007U) + }, + }; + const mpi_limb64_t zero = LIMB_TO64(0); + mpi_ptr_t wp; + mpi_ptr_t pp; + mpi_size_t wsize = (384 + BITS_PER_MPI_LIMB64 - 1) / BITS_PER_MPI_LIMB64; + mpi_size_t psize = ctx->p->nlimbs; +#if BITS_PER_MPI_LIMB64 == BITS_PER_MPI_LIMB + mpi_limb_t wp_shr32[wsize * LIMBS_PER_LIMB64]; +#endif + mpi_limb64_t s[wsize + 1]; + mpi_limb64_t t[wsize + 1]; + mpi_limb64_t d[wsize + 1]; + mpi_limb64_t x[wsize + 1]; + mpi_limb_t mask1; + mpi_limb_t mask2; + int carry; + + MPN_NORMALIZE (w->d, w->nlimbs); + if (mpi_nbits_more_than (w, 2 * 384)) + log_bug ("W must be less than m^2\n"); + + RESIZE_AND_CLEAR_IF_NEEDED (w, wsize * 2 * LIMBS_PER_LIMB64); + RESIZE_AND_CLEAR_IF_NEEDED (ctx->p, wsize * LIMBS_PER_LIMB64); + ctx->p->nlimbs = psize; + + pp = ctx->p->d; + wp = w->d; + + prefetch (p_mult, sizeof(p_mult)); + + /* See "FIPS 186-4, D.2.4 Curve P-384". */ + +#if BITS_PER_MPI_LIMB64 == BITS_PER_MPI_LIMB +# define LOAD64_SHR32(idx) LOAD64(wp_shr32, ((idx) / 2 - wsize)) + _gcry_mpih_rshift (wp_shr32, wp + 384 / BITS_PER_MPI_LIMB, + wsize * LIMBS_PER_LIMB64, 32); +#else +# define LOAD64_SHR32(idx) LIMB64_HILO(LOAD32(wp, (idx) + 1), LOAD32(wp, idx)) +#endif + + /* "S1 + S1" with 64-bit limbs: + * [0:A23]:[A22:A21] + * + [0:A23]:[A22:A21] + * => s[3]:s[2] + */ + ADD2_LIMB64 (s[3], s[2], + LIMB64_HILO(0, LOAD32(wp, 23)), + LOAD64_SHR32(21), + LIMB64_HILO(0, LOAD32(wp, 23)), + LOAD64_SHR32(21)); + + /* "S5 + S6" with 64-bit limbs: + * [A23:A22]:[A21:A20]:[ 0:0]:[0: 0] + * + [ 0: 0]:[A23:A22]:[A21:0]:[0:A20] + * => x[4]:x[3]:x[2]:x[1]:x[0] + */ + x[0] = LIMB64_HILO(0, LOAD32(wp, 20)); + x[1] = LIMB64_HILO(LOAD32(wp, 21), 0); + ADD3_LIMB64 (x[4], x[3], x[2], + zero, LOAD64(wp, 22 / 2), LOAD64(wp, 20 / 2), + zero, zero, LOAD64(wp, 22 / 2)); + + /* "D2 + D3" with 64-bit limbs: + * [0:A23]:[A22:A21]:[A20:0] + * + [0:A23]:[A23:0]:[0:0] + * => d[2]:d[1]:d[0] + */ + d[0] = LIMB64_HILO(LOAD32(wp, 20), 0); + ADD2_LIMB64 (d[2], d[1], + LIMB64_HILO(0, LOAD32(wp, 23)), + LOAD64_SHR32(21), + LIMB64_HILO(0, LOAD32(wp, 23)), + LIMB64_HILO(LOAD32(wp, 23), 0)); + + /* "2*S1 + S5 + S6" with 64-bit limbs: + * s[4]:s[3]:s[2]:s[1]:s[0] + * + x[4]:x[3]:x[2]:x[1]:x[0] + * => s[4]:s[3]:s[2]:s[1]:s[0] + */ + s[0] = x[0]; + s[1] = x[1]; + ADD3_LIMB64(s[4], s[3], s[2], + zero, s[3], s[2], + x[4], x[3], x[2]); + + /* "T + S2" with 64-bit limbs: + * [A11:A10]:[ A9: A8]:[ A7: A6]:[ A5: A4]:[ A3: A2]:[ A1: A0] + * + [A23:A22]:[A21:A20]:[A19:A18]:[A17:A16]:[A15:A14]:[A13:A12] + * => t[6]:t[5]:t[4]:t[3]:t[2]:t[1]:t[0] + */ + ADD7_LIMB64 (t[6], t[5], t[4], t[3], t[2], t[1], t[0], + zero, + LOAD64(wp, 10 / 2), LOAD64(wp, 8 / 2), LOAD64(wp, 6 / 2), + LOAD64(wp, 4 / 2), LOAD64(wp, 2 / 2), LOAD64(wp, 0 / 2), + zero, + LOAD64(wp, 22 / 2), LOAD64(wp, 20 / 2), LOAD64(wp, 18 / 2), + LOAD64(wp, 16 / 2), LOAD64(wp, 14 / 2), LOAD64(wp, 12 / 2)); + + /* "2*S1 + S4 + S5 + S6" with 64-bit limbs: + * s[6]: s[5]: s[4]: s[3]: s[2]: s[1]: s[0] + * + [A19:A18]:[A17:A16]:[A15:A14]:[A13:A12]:[A20:0]:[A23:0] + * => s[6]:s[5]:s[4]:s[3]:s[2]:s[1]:s[0] + */ + ADD7_LIMB64 (s[6], s[5], s[4], s[3], s[2], s[1], s[0], + zero, zero, s[4], s[3], s[2], s[1], s[0], + zero, + LOAD64(wp, 18 / 2), LOAD64(wp, 16 / 2), + LOAD64(wp, 14 / 2), LOAD64(wp, 12 / 2), + LIMB64_HILO(LOAD32(wp, 20), 0), + LIMB64_HILO(LOAD32(wp, 23), 0)); + + /* "D1 + D2 + D3" with 64-bit limbs: + * d[6]: d[5]: d[4]: d[3]: d[2]: d[1]: d[0] + * + [A22:A21]:[A20:A19]:[A18:A17]:[A16:A15]:[A14:A13]:[A12:A23] + * => d[6]:d[5]:d[4]:d[3]:d[2]:d[1]:d[0] + */ + ADD7_LIMB64 (d[6], d[5], d[4], d[3], d[2], d[1], d[0], + zero, zero, zero, zero, d[2], d[1], d[0], + zero, + LOAD64_SHR32(21), + LOAD64_SHR32(19), + LOAD64_SHR32(17), + LOAD64_SHR32(15), + LOAD64_SHR32(13), + LIMB64_HILO(LOAD32(wp, 12), LOAD32(wp, 23))); + + /* "2*S1 + S3 + S4 + S5 + S6" with 64-bit limbs: + * s[6]: s[5]: s[4]: s[3]: s[2]: s[1]: s[0] + * + [A20:A19]:[A18:A17]:[A16:A15]:[A14:A13]:[A12:A23]:[A22:A21] + * => s[6]:s[5]:s[4]:s[3]:s[2]:s[1]:s[0] + */ + ADD7_LIMB64 (s[6], s[5], s[4], s[3], s[2], s[1], s[0], + s[6], s[5], s[4], s[3], s[2], s[1], s[0], + zero, + LOAD64_SHR32(19), + LOAD64_SHR32(17), + LOAD64_SHR32(15), + LOAD64_SHR32(13), + LIMB64_HILO(LOAD32(wp, 12), LOAD32(wp, 23)), + LOAD64_SHR32(21)); + + /* "T + 2*S1 + S2 + S3 + S4 + S5 + S6" */ + ADD7_LIMB64 (s[6], s[5], s[4], s[3], s[2], s[1], s[0], + s[6], s[5], s[4], s[3], s[2], s[1], s[0], + t[6], t[5], t[4], t[3], t[2], t[1], t[0]); + + /* "T + 2*S1 + S2 + S3 + S4 + S5 + S6 - D1 - D2 - D3" */ + SUB7_LIMB64 (s[6], s[5], s[4], s[3], s[2], s[1], s[0], + s[6], s[5], s[4], s[3], s[2], s[1], s[0], + d[6], d[5], d[4], d[3], d[2], d[1], d[0]); + +#undef LOAD64_SHR32 + + /* mod p: + * 's[6]' holds carry value (-3..7). Subtract (carry + 1) * p. Result + * will be with in range -p...p. Handle result being negative with + * addition and conditional store. */ + + carry = LO32_LIMB64(s[6]); + + SUB7_LIMB64 (s[6], s[5], s[4], s[3], s[2], s[1], s[0], + s[6], s[5], s[4], s[3], s[2], s[1], s[0], + p_mult[carry + 3][6], p_mult[carry + 3][5], + p_mult[carry + 3][4], p_mult[carry + 3][3], + p_mult[carry + 3][2], p_mult[carry + 3][1], + p_mult[carry + 3][0]); + + ADD7_LIMB64 (d[6], d[5], d[4], d[3], d[2], d[1], d[0], + s[6], s[5], s[4], s[3], s[2], s[1], s[0], + zero, + LOAD64(pp, 5), LOAD64(pp, 4), + LOAD64(pp, 3), LOAD64(pp, 2), + LOAD64(pp, 1), LOAD64(pp, 0)); + + mask1 = vzero - (LO32_LIMB64(d[6]) >> 31); + mask2 = (LO32_LIMB64(d[6]) >> 31) - vone; + + STORE64_COND(wp, 0, mask2, d[0], mask1, s[0]); + STORE64_COND(wp, 1, mask2, d[1], mask1, s[1]); + STORE64_COND(wp, 2, mask2, d[2], mask1, s[2]); + STORE64_COND(wp, 3, mask2, d[3], mask1, s[3]); + STORE64_COND(wp, 4, mask2, d[4], mask1, s[4]); + STORE64_COND(wp, 5, mask2, d[5], mask1, s[5]); + + w->nlimbs = wsize * LIMBS_PER_LIMB64; + MPN_NORMALIZE (wp, w->nlimbs); +} + +void +_gcry_mpi_ec_nist521_mod (gcry_mpi_t w, mpi_ec_t ctx) +{ + mpi_size_t wsize = (521 + BITS_PER_MPI_LIMB - 1) / BITS_PER_MPI_LIMB; + mpi_limb_t s[wsize]; + mpi_limb_t cy; + mpi_ptr_t wp; + + MPN_NORMALIZE (w->d, w->nlimbs); + if (mpi_nbits_more_than (w, 2 * 521)) + log_bug ("W must be less than m^2\n"); + + RESIZE_AND_CLEAR_IF_NEEDED (w, wsize * 2); + + wp = w->d; + + /* See "FIPS 186-4, D.2.5 Curve P-521". */ + + _gcry_mpih_rshift (s, wp + wsize - 1, wsize, 521 % BITS_PER_MPI_LIMB); + s[wsize - 1] &= (1 << (521 % BITS_PER_MPI_LIMB)) - 1; + wp[wsize - 1] &= (1 << (521 % BITS_PER_MPI_LIMB)) - 1; + _gcry_mpih_add_n (wp, wp, s, wsize); + + /* "mod p" */ + cy = _gcry_mpih_sub_n (wp, wp, ctx->p->d, wsize); + _gcry_mpih_add_n (s, wp, ctx->p->d, wsize); + mpih_set_cond (wp, s, wsize, (cy != 0UL)); + + w->nlimbs = wsize; + MPN_NORMALIZE (wp, w->nlimbs); +} + +#endif /* !ASM_DISABLED */ diff --git a/mpi/ec.c b/mpi/ec.c index 4fabf9b4..ae1d036a 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -285,7 +285,7 @@ static void ec_addm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) { mpi_add (w, u, v); - ec_mod (w, ctx); + ctx->mod (w, ctx); } static void @@ -294,14 +294,14 @@ ec_subm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ec) mpi_sub (w, u, v); while (w->sign) mpi_add (w, w, ec->p); - /*ec_mod (w, ec);*/ + /*ctx->mod (w, ec);*/ } static void ec_mulm (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx) { mpi_mul (w, u, v); - ec_mod (w, ctx); + ctx->mod (w, ctx); } /* W = 2 * U mod P. */ @@ -309,7 +309,7 @@ static void ec_mul2 (gcry_mpi_t w, gcry_mpi_t u, mpi_ec_t ctx) { mpi_lshift (w, u, 1); - ec_mod (w, ctx); + ctx->mod (w, ctx); } static void @@ -585,6 +585,7 @@ struct field_table { void (* mulm) (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx); void (* mul2) (gcry_mpi_t w, gcry_mpi_t u, mpi_ec_t ctx); void (* pow2) (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx); + void (* mod) (gcry_mpi_t w, mpi_ec_t ctx); }; static const struct field_table field_table[] = { @@ -594,7 +595,8 @@ static const struct field_table field_table[] = { ec_subm_25519, ec_mulm_25519, ec_mul2_25519, - ec_pow2_25519 + ec_pow2_25519, + NULL }, { "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" @@ -603,7 +605,55 @@ static const struct field_table field_table[] = { ec_subm_448, ec_mulm_448, ec_mul2_448, - ec_pow2_448 + ec_pow2_448, + NULL + }, + { + "0xfffffffffffffffffffffffffffffffeffffffffffffffff", + NULL, + NULL, + NULL, + NULL, + NULL, + _gcry_mpi_ec_nist192_mod + }, + { + "0xffffffffffffffffffffffffffffffff000000000000000000000001", + NULL, + NULL, + NULL, + NULL, + NULL, + _gcry_mpi_ec_nist224_mod + }, + { + "0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + NULL, + NULL, + NULL, + NULL, + NULL, + _gcry_mpi_ec_nist256_mod + }, + { + "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" + "ffffffff0000000000000000ffffffff", + NULL, + NULL, + NULL, + NULL, + NULL, + _gcry_mpi_ec_nist384_mod + }, + { + "0x01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + NULL, + NULL, + NULL, + NULL, + NULL, + _gcry_mpi_ec_nist521_mod }, { NULL, NULL, NULL, NULL, NULL, NULL }, }; @@ -757,6 +807,7 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model, ctx->mulm = ec_mulm; ctx->mul2 = ec_mul2; ctx->pow2 = ec_pow2; + ctx->mod = ec_mod; for (i=0; field_table[i].p; i++) { @@ -769,18 +820,25 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model, if (!mpi_cmp (p, f_p)) { - ctx->addm = field_table[i].addm; - ctx->subm = field_table[i].subm; - ctx->mulm = field_table[i].mulm; - ctx->mul2 = field_table[i].mul2; - ctx->pow2 = field_table[i].pow2; + ctx->addm = field_table[i].addm ? field_table[i].addm : ctx->addm; + ctx->subm = field_table[i].subm ? field_table[i].subm : ctx->subm; + ctx->mulm = field_table[i].mulm ? field_table[i].mulm : ctx->mulm; + ctx->mul2 = field_table[i].mul2 ? field_table[i].mul2 : ctx->mul2; + ctx->pow2 = field_table[i].pow2 ? field_table[i].pow2 : ctx->pow2; + ctx->mod = field_table[i].mod ? field_table[i].mod : ctx->mod; _gcry_mpi_release (f_p); - mpi_resize (ctx->a, ctx->p->nlimbs); - ctx->a->nlimbs = ctx->p->nlimbs; - - mpi_resize (ctx->b, ctx->p->nlimbs); - ctx->b->nlimbs = ctx->p->nlimbs; + if (ctx->a) + { + mpi_resize (ctx->a, ctx->p->nlimbs); + ctx->a->nlimbs = ctx->p->nlimbs; + } + + if (ctx->b) + { + mpi_resize (ctx->b, ctx->p->nlimbs); + ctx->b->nlimbs = ctx->p->nlimbs; + } for (i=0; i< DIM(ctx->t.scratch) && ctx->t.scratch[i]; i++) ctx->t.scratch[i]->nlimbs = ctx->p->nlimbs; diff --git a/mpi/mpi-internal.h b/mpi/mpi-internal.h index 8ccdeada..11fcbde4 100644 --- a/mpi/mpi-internal.h +++ b/mpi/mpi-internal.h @@ -79,6 +79,11 @@ typedef int mpi_size_t; /* (must be a signed type) */ if( (a)->alloced < (b) ) \ mpi_resize((a), (b)); \ } while(0) +#define RESIZE_AND_CLEAR_IF_NEEDED(a,b) \ + do { \ + if( (a)->nlimbs < (b) ) \ + mpi_resize((a), (b)); \ + } while(0) /* Copy N limbs from S to D. */ #define MPN_COPY( d, s, n) \ diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c index 5320f4d8..a5583c79 100644 --- a/mpi/mpiutil.c +++ b/mpi/mpiutil.c @@ -197,7 +197,7 @@ _gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs) if (a->d) { a->d = xrealloc (a->d, nlimbs * sizeof (mpi_limb_t)); - for (i=a->alloced; i < nlimbs; i++) + for (i=a->nlimbs; i < nlimbs; i++) a->d[i] = 0; } else diff --git a/src/ec-context.h b/src/ec-context.h index d1c64804..479862f6 100644 --- a/src/ec-context.h +++ b/src/ec-context.h @@ -74,6 +74,7 @@ struct mpi_ec_ctx_s void (* mulm) (gcry_mpi_t w, gcry_mpi_t u, gcry_mpi_t v, mpi_ec_t ctx); void (* pow2) (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx); void (* mul2) (gcry_mpi_t w, gcry_mpi_t u, mpi_ec_t ctx); + void (* mod) (gcry_mpi_t w, mpi_ec_t ctx); }; -- 2.30.2 From hjl.tools at gmail.com Tue Apr 27 18:29:28 2021 From: hjl.tools at gmail.com (H.J. Lu) Date: Tue, 27 Apr 2021 09:29:28 -0700 Subject: [PATCH] Always include in cipher assembly codes Message-ID: <20210427162928.849963-1-hjl.tools@gmail.com> * cipher/poly1305-s390x.S: Always include . When Intel CET is enabled, we need to include in assembly codes to mark Intel CET support even if it is empty. We should always include in cipher assembly codes so that they will be marked for Intel CET support when compiling for x86-64 and i686. Signed-off-by: H.J. Lu --- cipher/poly1305-s390x.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cipher/poly1305-s390x.S b/cipher/poly1305-s390x.S index 844245f6..28bed560 100644 --- a/cipher/poly1305-s390x.S +++ b/cipher/poly1305-s390x.S @@ -18,8 +18,8 @@ * License along with this program; if not, see . */ -#if defined (__s390x__) && __GNUC__ >= 4 && __ARCH__ >= 9 #include +#if defined (__s390x__) && __GNUC__ >= 4 && __ARCH__ >= 9 #if defined(HAVE_GCC_INLINE_ASM_S390X) #include "asm-poly1305-s390x.h" -- 2.31.1 From vimacs at disroot.org Wed Apr 28 03:27:05 2021 From: vimacs at disroot.org (Iru Cai) Date: Wed, 28 Apr 2021 09:27:05 +0800 Subject: i386 get_cpuid() function looks wrong Message-ID: Hello, I built libgcrypt for 32-bit x86, and it reports wrong CPU hardware features. After some debugging, I found the get_cpuid() function go wrong. This function use some inline assembly code: asm volatile ("movl %%ebx, %%edi\n\t" /* Save GOT register. */ "xorl %%ebx, %%ebx\n\t" "cpuid\n\t" "movl %%ebx, %1\n\t" "movl %%edi, %%ebx\n\t" /* Restore GOT register. */ : "=a" (regs[0]), "=g" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) : "0" (in), "2" (0), "3" (0) : "cc", "edi" ); When I build libgcrypt with CFLAGS '-m32 -march=i686 -Os', '%1' in the above assembly code can be assigned to ebx, thus the code go wrong. After checking the GCC manual, "=g" means any register, so the compiler can allocate ebx to it. Regards, Iru From jussi.kivilinna at iki.fi Wed Apr 28 18:41:12 2021 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 28 Apr 2021 19:41:12 +0300 Subject: i386 get_cpuid() function looks wrong In-Reply-To: References: Message-ID: <21054180-b4b5-3869-26b0-5932208a4813@iki.fi> Hello, On 28.4.2021 4.27, Iru Cai via Gcrypt-devel wrote: > Hello, > > I built libgcrypt for 32-bit x86, and it reports wrong CPU hardware features. After some debugging, I found the get_cpuid() function go wrong. This function use some inline assembly code: > > ? asm volatile > ??? ("movl %%ebx, %%edi\n\t"???? /* Save GOT register.? */ > ???? "xorl %%ebx, %%ebx\n\t" > ???? "cpuid\n\t" > ???? "movl %%ebx, %1\n\t" > ???? "movl %%edi, %%ebx\n\t"???? /* Restore GOT register. */ > ???? : "=a" (regs[0]), "=g" (regs[1]), "=c" (regs[2]), "=d" (regs[3]) > ???? : "0" (in), "2" (0), "3" (0) > ???? : "cc", "edi" > ???? ); > > When I build libgcrypt with CFLAGS '-m32 -march=i686 -Os', '%1' in the above assembly code can be assigned to ebx, thus the code go wrong. After checking the GCC manual, "=g" means any register, so the compiler can allocate ebx to it. > Thanks for reporting this. You're right, that "=g" is wrong there. I've attached patch that fixes issue by using %edi register operand instead and swapping %ebx contents with %edi before and after cpuid. -Jussi -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-hwf-x86-fix-use-of-wrong-type-operand.patch Type: text/x-patch Size: 1754 bytes Desc: not available URL: From udoy.soumik at gmail.com Fri Apr 30 13:47:57 2021 From: udoy.soumik at gmail.com (Salman Soumik) Date: Fri, 30 Apr 2021 17:47:57 +0600 Subject: Libgcrypt 1.9.3 fails to build on MacOS for arm64 architecture Message-ID: Hello, I am trying to build libgcrypt 1.9.3 for iOS arm64 architecture using XCode commandline tool. On macos 11.1 and Xcode 12.4, I am getting this error while building: *"use of undeclared identifier 'getentropy'" .* FYI, libgcrypt 1.9.2 and prior versions can be built without issues on the same platform. Here's the configuration I'm trying to build: Libgcrypt v1.9.3 has been configured as follows: Platform: Darwin (aarch64-apple-darwin) Hardware detection module: none Enabled cipher algorithms: arcfour blowfish cast5 des aes twofish serpent rfc2268 seed camellia idea salsa20 gost28147 chacha20 sm4 Enabled digest algorithms: crc gostr3411-94 md4 md5 rmd160 sha1 sha256 sha512 sha3 tiger whirlpool stribog blake2 sm3 Enabled kdf algorithms: s2k pkdf2 scrypt Enabled pubkey algorithms: dsa elgamal rsa ecc Random number generator: default Try using jitter entropy: yes Using linux capabilities: no Try using Padlock crypto: n/a Try using AES-NI crypto: n/a Try using Intel SHAEXT: n/a Try using Intel PCLMUL: n/a Try using Intel SSE4.1: n/a Try using DRNG (RDRAND): n/a Try using Intel AVX: n/a Try using Intel AVX2: n/a Try using ARM NEON: n/a Try using ARMv8 crypto: n/a Try using PPC crypto: n/a Here's the make command that fails: libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -I../src -I../src -I/Users/soumik/Downloads/OTRKit-master/scripts/build/iPhoneOS-14.4-arm64/include -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.4.sdk -I/Users/soumik/Downloads/OTRKit-master/scripts/built/arm64/include -miphoneos-version-min=8.0 -fembed-bitcode -fno-delete-null-pointer-checks -Wall -MT rndlinux.lo -MD -MP -MF .deps/rndlinux.Tpo -c rndlinux.c -fno-common -DPIC -o rndlinux.o Do I need to make any change for building 1.9.3? Or there's issue on libgcrypt that needs to be addressed? Thank you. Kind Regards, Udoy Soumik -------------- next part -------------- An HTML attachment was scrubbed... URL: